Merge branch 'master' into careminster

Conflicts:
	OpenSim/Framework/RegionSettings.cs
	OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
	OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
	OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
avinationmerge
Melanie 2014-01-28 21:02:20 +00:00
commit c6e9db5866
59 changed files with 2161 additions and 1675 deletions

View File

@ -1,5 +1,4 @@
<<<>>>>The following people have contributed to OpenSim (Thank you The following people have contributed to OpenSim (Thank you for your effort!)
for your effort!)
= Current OpenSim Developers (in very rough order of appearance) = = Current OpenSim Developers (in very rough order of appearance) =
These folks represent the current core team for OpenSim, and are the These folks represent the current core team for OpenSim, and are the
@ -61,8 +60,9 @@ where we are today.
These folks have contributed code patches or content to OpenSimulator to help make it These folks have contributed code patches or content to OpenSimulator to help make it
what it is today. what it is today.
* aduffy70
* A_Biondi * A_Biondi
* aduffy70
* Ai Austin
* alex_carnell * alex_carnell
* Alan Webb (IBM) * Alan Webb (IBM)
* Aleric * Aleric
@ -173,23 +173,18 @@ what it is today.
* Zha Ewry * Zha Ewry
* ziah * ziah
= LSL Devs = = LSL Devs =
* Alondria * Alondria
* CharlieO * CharlieO
* Tedd * Tedd
* Melanie Thielker * Melanie Thielker
= Testers = = Testers =
* Ai Austin * Ai Austin
* CharlieO (LSL) * CharlieO (LSL)
* Ckrinke * Ckrinke
* openlifegrid.com * openlifegrid.com
This software uses components from the following developers: This software uses components from the following developers:
* Sleepycat Software (Berkeley DB) * Sleepycat Software (Berkeley DB)
* Aurora-Sim (http://aurora-sim.org) * Aurora-Sim (http://aurora-sim.org)

View File

@ -261,6 +261,11 @@ namespace OpenSim.OfflineIM
return m_OfflineIMService.StoreMessage(im, out reason); return m_OfflineIMService.StoreMessage(im, out reason);
} }
public void DeleteMessages(UUID userID)
{
m_OfflineIMService.DeleteMessages(userID);
}
#endregion #endregion
} }
} }

View File

@ -117,6 +117,14 @@ namespace OpenSim.OfflineIM
return true; return true;
} }
public void DeleteMessages(UUID userID)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["UserID"] = userID;
MakeRequest("DELETE", sendData);
}
#endregion #endregion

View File

@ -1,4 +1,4 @@
/* /*
* 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.
* *
@ -96,13 +96,14 @@ namespace OpenSim.OfflineIM
string method = request["METHOD"].ToString(); string method = request["METHOD"].ToString();
request.Remove("METHOD"); request.Remove("METHOD");
m_log.DebugFormat("[OfflineIM.V2.Handler]: {0}", method);
switch (method) switch (method)
{ {
case "GET": case "GET":
return HandleGet(request); return HandleGet(request);
case "STORE": case "STORE":
return HandleStore(request); return HandleStore(request);
case "DELETE":
return HandleDelete(request);
} }
m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method); m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method);
} }
@ -159,6 +160,21 @@ namespace OpenSim.OfflineIM
return Util.UTF8NoBomEncoding.GetBytes(xmlString); return Util.UTF8NoBomEncoding.GetBytes(xmlString);
} }
byte[] HandleDelete(Dictionary<string, object> request)
{
if (!request.ContainsKey("UserID"))
{
return FailureResult();
}
else
{
UUID userID = new UUID(request["UserID"].ToString());
m_OfflineIMService.DeleteMessages(userID);
return SuccessResult();
}
}
#region Helpers #region Helpers
private void NullResult(Dictionary<string, object> result, string reason) private void NullResult(Dictionary<string, object> result, string reason)

View File

@ -1,4 +1,4 @@
/* /*
* 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.
* *
@ -91,7 +91,7 @@ namespace OpenSim.OfflineIM
{ {
reason = string.Empty; reason = string.Empty;
// TODO Check limits // Check limits
UUID principalID = new UUID(im.toAgentID); UUID principalID = new UUID(im.toAgentID);
long count = m_Database.GetCount("PrincipalID", principalID.ToString()); long count = m_Database.GetCount("PrincipalID", principalID.ToString());
if (count >= MAX_IM) if (count >= MAX_IM)
@ -100,7 +100,7 @@ namespace OpenSim.OfflineIM
return false; return false;
} }
string imXml = string.Empty; string imXml;
using (MemoryStream mstream = new MemoryStream()) using (MemoryStream mstream = new MemoryStream())
{ {
XmlWriterSettings settings = new XmlWriterSettings(); XmlWriterSettings settings = new XmlWriterSettings();
@ -110,22 +110,26 @@ namespace OpenSim.OfflineIM
{ {
m_serializer.Serialize(writer, im); m_serializer.Serialize(writer, im);
writer.Flush(); writer.Flush();
mstream.Position = 0;
using (StreamReader sreader = new StreamReader(mstream))
{
imXml = sreader.ReadToEnd();
}
} }
imXml = Util.UTF8.GetString(mstream.ToArray());
} }
OfflineIMData data = new OfflineIMData(); OfflineIMData data = new OfflineIMData();
data.PrincipalID = principalID; data.PrincipalID = principalID;
data.FromID = new UUID(im.fromAgentID);
data.Data = new Dictionary<string, string>(); data.Data = new Dictionary<string, string>();
data.Data["Message"] = imXml; data.Data["Message"] = imXml;
return m_Database.Store(data); return m_Database.Store(data);
} }
public void DeleteMessages(UUID userID)
{
m_Database.Delete("PrincipalID", userID.ToString());
m_Database.Delete("FromID", userID.ToString());
}
} }
} }

View File

@ -1,4 +1,4 @@
/* /*
* 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.
* *
@ -34,6 +34,7 @@ namespace OpenSim.Data
public class OfflineIMData public class OfflineIMData
{ {
public UUID PrincipalID; public UUID PrincipalID;
public UUID FromID;
public Dictionary<string, string> Data; public Dictionary<string, string> Data;
} }

View File

@ -21,4 +21,14 @@ INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
DROP TABLE `diva_im_offline`; DROP TABLE `diva_im_offline`;
DELETE FROM `migrations` WHERE name='diva_im_Store'; DELETE FROM `migrations` WHERE name='diva_im_Store';
COMMIT; COMMIT;
:VERSION 3 # --------------------------
BEGIN;
ALTER TABLE `im_offline`
ADD `FromID` char(36) NOT NULL default '' AFTER `PrincipalID`,
ADD KEY `FromID` (`FromID`);
COMMIT;

View File

@ -31,10 +31,34 @@ namespace OpenSim.Framework
{ {
public interface IImprovedAssetCache public interface IImprovedAssetCache
{ {
/// <summary>
/// Cache the specified asset.
/// </summary>
/// <param name='asset'></param>
void Cache(AssetBase asset); void Cache(AssetBase asset);
/// <summary>
/// Get an asset by its id.
/// </summary>
/// <param name='id'></param>
/// <returns>null if the asset does not exist.</returns>
AssetBase Get(string id); AssetBase Get(string id);
/// <summary>
/// Check whether an asset with the specified id exists in the cache.
/// </summary>
/// <param name='id'></param>
bool Check(string id); bool Check(string id);
/// <summary>
/// Expire an asset from the cache.
/// </summary>
/// <param name='id'></param>
void Expire(string id); void Expire(string id);
/// <summary>
/// Clear the cache.
/// </summary>
void Clear(); void Clear();
} }
} }

View File

@ -504,21 +504,14 @@ namespace OpenSim.Framework
set { m_TelehubEnabled = value; } set { m_TelehubEnabled = value; }
} }
// Connected Telehub object /// <summary>
private UUID m_TelehubObject = UUID.Zero; /// Connected Telehub object
public UUID TelehubObject /// </summary>
{ public UUID TelehubObject { get; set; }
get
{
return m_TelehubObject;
}
set
{
m_TelehubObject = value;
}
}
// Our Connected Telehub's SpawnPoints /// <summary>
/// Our connected Telehub's SpawnPoints
/// </summary>
public List<SpawnPoint> l_SpawnPoints = new List<SpawnPoint>(); public List<SpawnPoint> l_SpawnPoints = new List<SpawnPoint>();
// Add a SpawnPoint // Add a SpawnPoint
@ -549,4 +542,4 @@ namespace OpenSim.Framework
l_SpawnPoints.Clear(); l_SpawnPoints.Clear();
} }
} }
} }

View File

@ -39,8 +39,32 @@ namespace OpenSim.Framework
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Asset types used only in OpenSim.
/// To avoid clashing with the code numbers used in Second Life, use only negative numbers here.
/// </summary>
public enum OpenSimAssetType : sbyte
{
Material = -2
}
#region SL / file extension / content-type conversions #region SL / file extension / content-type conversions
/// <summary>
/// Returns the Enum entry corresponding to the given code, regardless of whether it belongs
/// to the AssetType or OpenSimAssetType enums.
/// </summary>
public static object AssetTypeFromCode(sbyte assetType)
{
if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
return (OpenMetaverse.AssetType)assetType;
else if (Enum.IsDefined(typeof(OpenSimAssetType), assetType))
return (OpenSimAssetType)assetType;
else
return OpenMetaverse.AssetType.Unknown;
}
private class TypeMapping private class TypeMapping
{ {
private sbyte assetType; private sbyte assetType;
@ -56,12 +80,7 @@ namespace OpenSim.Framework
public object AssetType public object AssetType
{ {
get { get { return AssetTypeFromCode(assetType); }
if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
return (OpenMetaverse.AssetType)assetType;
else
return OpenMetaverse.AssetType.Unknown;
}
} }
public InventoryType InventoryType public InventoryType InventoryType
@ -102,6 +121,11 @@ namespace OpenSim.Framework
: this((sbyte)assetType, inventoryType, contentType, null, extension) : this((sbyte)assetType, inventoryType, contentType, null, extension)
{ {
} }
public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension)
: this((sbyte)assetType, inventoryType, contentType, null, extension)
{
}
} }
/// <summary> /// <summary>
@ -142,7 +166,9 @@ namespace OpenSim.Framework
new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"), new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"), new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"), new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm") new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"),
new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material")
}; };
private static Dictionary<sbyte, string> asset2Content; private static Dictionary<sbyte, string> asset2Content;

View File

@ -29,6 +29,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using OpenMetaverse; using OpenMetaverse;
using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
namespace OpenSim.Framework.Serialization namespace OpenSim.Framework.Serialization
{ {
@ -128,6 +129,7 @@ namespace OpenSim.Framework.Serialization
ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2";
ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga";
ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this
ASSET_TYPE_TO_EXTENSION[(sbyte)OpenSimAssetType.Material] = ASSET_EXTENSION_SEPARATOR + "material.xml"; // Not sure if we'll ever see this
EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation;
EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart;
@ -152,6 +154,7 @@ namespace OpenSim.Framework.Serialization
EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture;
EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA;
EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder;
EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "material.xml"] = (sbyte)OpenSimAssetType.Material;
} }
public static string CreateOarLandDataPath(LandData ld) public static string CreateOarLandDataPath(LandData ld)

View File

@ -1043,7 +1043,7 @@ namespace OpenSim.Framework
else if (typeof(T) == typeof(Int32)) else if (typeof(T) == typeof(Int32))
val = cnf.GetInt(varname, (int)val); val = cnf.GetInt(varname, (int)val);
else if (typeof(T) == typeof(float)) else if (typeof(T) == typeof(float))
val = cnf.GetFloat(varname, (int)val); val = cnf.GetFloat(varname, (float)val);
else else
m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T)); m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T));
} }

View File

@ -124,7 +124,7 @@ namespace OpenSim
else else
{ {
Application.iniFilePath = Path.GetFullPath( Application.iniFilePath = Path.GetFullPath(
Path.Combine(Util.configDir(), iniFileName)); Path.Combine(Util.configDir(), iniFileName));
if (!File.Exists(Application.iniFilePath)) if (!File.Exists(Application.iniFilePath))
{ {
@ -139,12 +139,29 @@ namespace OpenSim
} }
} }
m_config = new OpenSimConfigSource();
m_config.Source = new IniConfigSource();
m_config.Source.Merge(DefaultConfig());
m_log.Info("[CONFIG]: Reading configuration settings");
for (int i = 0 ; i < sources.Count ; i++)
{
if (ReadConfig(m_config, sources[i]))
{
iniFileExists = true;
AddIncludes(m_config, sources);
}
}
// Override distro settings with contents of inidirectory
string iniDirName = startupConfig.GetString("inidirectory", "config"); string iniDirName = startupConfig.GetString("inidirectory", "config");
string iniDirPath = Path.Combine(Util.configDir(), iniDirName); string iniDirPath = Path.Combine(Util.configDir(), iniDirName);
if (Directory.Exists(iniDirPath)) if (Directory.Exists(iniDirPath))
{ {
m_log.InfoFormat("Searching folder {0} for config ini files", iniDirPath); m_log.InfoFormat("[CONFIG]: Searching folder {0} for config ini files", iniDirPath);
List<string> overrideSources = new List<string>();
string[] fileEntries = Directory.GetFiles(iniDirName); string[] fileEntries = Directory.GetFiles(iniDirName);
foreach (string filePath in fileEntries) foreach (string filePath in fileEntries)
@ -152,33 +169,38 @@ namespace OpenSim
if (Path.GetExtension(filePath).ToLower() == ".ini") if (Path.GetExtension(filePath).ToLower() == ".ini")
{ {
if (!sources.Contains(Path.GetFullPath(filePath))) if (!sources.Contains(Path.GetFullPath(filePath)))
{
overrideSources.Add(Path.GetFullPath(filePath));
// put it in sources too, to avoid circularity
sources.Add(Path.GetFullPath(filePath)); sources.Add(Path.GetFullPath(filePath));
}
} }
} }
if (overrideSources.Count > 0)
{
OpenSimConfigSource overrideConfig = new OpenSimConfigSource();
overrideConfig.Source = new IniConfigSource();
for (int i = 0 ; i < overrideSources.Count ; i++)
{
if (ReadConfig(overrideConfig, overrideSources[i]))
{
iniFileExists = true;
AddIncludes(overrideConfig, overrideSources);
}
}
m_config.Source.Merge(overrideConfig.Source);
}
} }
m_config = new OpenSimConfigSource();
m_config.Source = new IniConfigSource();
m_config.Source.Merge(DefaultConfig());
m_log.Info("[CONFIG]: Reading configuration settings");
if (sources.Count == 0) if (sources.Count == 0)
{ {
m_log.FatalFormat("[CONFIG]: Could not load any configuration"); m_log.FatalFormat("[CONFIG]: Could not load any configuration");
Environment.Exit(1); Environment.Exit(1);
} }
else if (!iniFileExists)
for (int i = 0 ; i < sources.Count ; i++)
{
if (ReadConfig(sources[i]))
{
iniFileExists = true;
AddIncludes(sources);
}
}
if (!iniFileExists)
{ {
m_log.FatalFormat("[CONFIG]: Could not load any configuration"); m_log.FatalFormat("[CONFIG]: Could not load any configuration");
m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!"); m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!");
@ -214,10 +236,10 @@ namespace OpenSim
/// Adds the included files as ini configuration files /// Adds the included files as ini configuration files
/// </summary> /// </summary>
/// <param name="sources">List of URL strings or filename strings</param> /// <param name="sources">List of URL strings or filename strings</param>
private void AddIncludes(List<string> sources) private void AddIncludes(OpenSimConfigSource configSource, List<string> sources)
{ {
//loop over config sources //loop over config sources
foreach (IConfig config in m_config.Source.Configs) foreach (IConfig config in configSource.Source.Configs)
{ {
// Look for Include-* in the key name // Look for Include-* in the key name
string[] keys = config.GetKeys(); string[] keys = config.GetKeys();
@ -284,7 +306,7 @@ namespace OpenSim
/// </summary> /// </summary>
/// <param name="iniPath">Full path to the ini</param> /// <param name="iniPath">Full path to the ini</param>
/// <returns></returns> /// <returns></returns>
private bool ReadConfig(string iniPath) private bool ReadConfig(OpenSimConfigSource configSource, string iniPath)
{ {
bool success = false; bool success = false;
@ -292,7 +314,7 @@ namespace OpenSim
{ {
m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath)); m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath));
m_config.Source.Merge(new IniConfigSource(iniPath)); configSource.Source.Merge(new IniConfigSource(iniPath));
success = true; success = true;
} }
else else
@ -305,7 +327,7 @@ namespace OpenSim
{ {
XmlReader r = XmlReader.Create(iniPath); XmlReader r = XmlReader.Create(iniPath);
XmlConfigSource cs = new XmlConfigSource(r); XmlConfigSource cs = new XmlConfigSource(r);
m_config.Source.Merge(cs); configSource.Source.Merge(cs);
success = true; success = true;
} }

View File

@ -163,6 +163,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_maxRTO = 60000; private int m_maxRTO = 60000;
public bool m_deliverPackets = true; public bool m_deliverPackets = true;
/// <summary>
/// This is the percentage of the udp texture queue to add to the task queue since
/// textures are now generally handled through http.
/// </summary>
private double m_cannibalrate = 0.0;
private ClientInfo m_info = new ClientInfo(); private ClientInfo m_info = new ClientInfo();
/// <summary> /// <summary>
@ -202,6 +208,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Create an array of token buckets for this clients different throttle categories // Create an array of token buckets for this clients different throttle categories
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
m_cannibalrate = rates.CannibalizeTextureRate;
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
{ {
ThrottleOutPacketType type = (ThrottleOutPacketType)i; ThrottleOutPacketType type = (ThrottleOutPacketType)i;
@ -350,6 +358,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
texture = Math.Max(texture, LLUDPServer.MTU); texture = Math.Max(texture, LLUDPServer.MTU);
asset = Math.Max(asset, LLUDPServer.MTU); asset = Math.Max(asset, LLUDPServer.MTU);
// Since most textures are now delivered through http, make it possible
// to cannibalize some of the bw from the texture throttle to use for
// the task queue (e.g. object updates)
task = task + (int)(m_cannibalrate * texture);
texture = (int)((1 - m_cannibalrate) * texture);
//int total = resend + land + wind + cloud + task + texture + asset; //int total = resend + land + wind + cloud + task + texture + asset;
//m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
// AgentID, resend, land, wind, cloud, task, texture, asset, total); // AgentID, resend, land, wind, cloud, task, texture, asset, total);

View File

@ -59,6 +59,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <summary>Flag used to enable adaptive throttles</summary> /// <summary>Flag used to enable adaptive throttles</summary>
public bool AdaptiveThrottlesEnabled; public bool AdaptiveThrottlesEnabled;
/// <summary>Amount of the texture throttle to steal for the task throttle</summary>
public double CannibalizeTextureRate;
/// <summary> /// <summary>
/// Default constructor /// Default constructor
/// </summary> /// </summary>
@ -80,6 +83,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Total = throttleConfig.GetInt("client_throttle_max_bps", 0); Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9);
} }
catch (Exception) { } catch (Exception) { }
} }

View File

@ -194,10 +194,12 @@ namespace OpenSim.Region.CoreModules.Asset
#region IImprovedAssetCache Members #region IImprovedAssetCache Members
public bool Check(string id) public bool Check(string id)
{ {
return false; AssetBase asset;
// XXX:This is probably not an efficient implementation.
return m_cache.TryGetValue(id, out asset);
} }
/// <summary> /// <summary>

View File

@ -114,7 +114,8 @@ namespace OpenSim.Region.CoreModules.Asset
// //
public bool Check(string id) public bool Check(string id)
{ {
return false; // XXX This is probably not an efficient implementation.
return Get(id) != null;
} }
public void Cache(AssetBase asset) public void Cache(AssetBase asset)

View File

@ -248,70 +248,67 @@ namespace OpenSim.Region.CoreModules.Asset
private void UpdateFileCache(string key, AssetBase asset) private void UpdateFileCache(string key, AssetBase asset)
{ {
// TODO: Spawn this off to some seperate thread to do the actual writing string filename = GetFileName(key);
if (asset != null)
try
{ {
string filename = GetFileName(key); // If the file is already cached, don't cache it, just touch it so access time is updated
if (File.Exists(filename))
try
{ {
// If the file is already cached, don't cache it, just touch it so access time is updated // We don't really want to know about sharing
if (File.Exists(filename)) // violations here. If the file is locked, then
// the other thread has updated the time for us.
try
{ {
// We don't really want to know about sharing
// violations here. If the file is locked, then
// the other thread has updated the time for us.
try
{
lock (m_CurrentlyWriting)
{
if (!m_CurrentlyWriting.Contains(filename))
File.SetLastAccessTime(filename, DateTime.Now);
}
}
catch
{
}
} else {
// 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
// same file multiple times.
lock (m_CurrentlyWriting) lock (m_CurrentlyWriting)
{ {
if (!m_CurrentlyWriting.Contains(filename))
File.SetLastAccessTime(filename, DateTime.Now);
}
}
catch
{
}
}
else
{
// 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
// same file multiple times.
lock (m_CurrentlyWriting)
{
#if WAIT_ON_INPROGRESS_REQUESTS #if WAIT_ON_INPROGRESS_REQUESTS
if (m_CurrentlyWriting.ContainsKey(filename)) if (m_CurrentlyWriting.ContainsKey(filename))
{ {
return; return;
} }
else else
{ {
m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
}
#else
if (m_CurrentlyWriting.Contains(filename))
{
return;
}
else
{
m_CurrentlyWriting.Add(filename);
}
#endif
} }
Util.FireAndForget( #else
delegate { WriteFileCache(filename, asset); }); if (m_CurrentlyWriting.Contains(filename))
{
return;
}
else
{
m_CurrentlyWriting.Add(filename);
}
#endif
} }
Util.FireAndForget(
delegate { WriteFileCache(filename, asset); });
} }
catch (Exception e) }
{ catch (Exception e)
m_log.ErrorFormat( {
"[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}", m_log.ErrorFormat(
asset.ID, e.Message, e.StackTrace); "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
} asset.ID, e.Message, e.StackTrace);
} }
} }
@ -347,15 +344,9 @@ namespace OpenSim.Region.CoreModules.Asset
private bool CheckFromMemoryCache(string id) private bool CheckFromMemoryCache(string id)
{ {
AssetBase asset = null; return m_MemoryCache.Contains(id);
if (m_MemoryCache.TryGetValue(id, out asset))
return true;
return false;
} }
/// <summary> /// <summary>
/// Try to get an asset from the file cache. /// Try to get an asset from the file cache.
/// </summary> /// </summary>
@ -393,15 +384,16 @@ namespace OpenSim.Region.CoreModules.Asset
if (File.Exists(filename)) if (File.Exists(filename))
{ {
FileStream stream = null;
try try
{ {
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
BinaryFormatter bformatter = new BinaryFormatter(); {
BinaryFormatter bformatter = new BinaryFormatter();
asset = (AssetBase)bformatter.Deserialize(stream); asset = (AssetBase)bformatter.Deserialize(stream);
m_DiskHits++; m_DiskHits++;
}
} }
catch (System.Runtime.Serialization.SerializationException e) catch (System.Runtime.Serialization.SerializationException e)
{ {
@ -420,12 +412,6 @@ namespace OpenSim.Region.CoreModules.Asset
m_log.WarnFormat( m_log.WarnFormat(
"[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
filename, id, e.Message, e.StackTrace); filename, id, e.Message, e.StackTrace);
}
finally
{
if (stream != null)
stream.Close();
} }
} }
@ -437,36 +423,19 @@ namespace OpenSim.Region.CoreModules.Asset
bool found = false; bool found = false;
string filename = GetFileName(id); string filename = GetFileName(id);
if (File.Exists(filename)) if (File.Exists(filename))
{ {
// actually check if we can open it, and so update expire
FileStream stream = null;
try try
{ {
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
if (stream != null)
{ {
found = true; if (stream != null)
stream.Close(); found = true;
} }
}
catch (System.Runtime.Serialization.SerializationException e)
{
found = false;
m_log.ErrorFormat(
"[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
filename, id, e.Message, e.StackTrace);
// 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) catch (Exception e)
{ {
found = false;
m_log.ErrorFormat( m_log.ErrorFormat(
"[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
filename, id, e.Message, e.StackTrace); filename, id, e.Message, e.StackTrace);
@ -518,11 +487,6 @@ namespace OpenSim.Region.CoreModules.Asset
return Get(id); return Get(id);
} }
public AssetBase CheckCached(string id)
{
return Get(id);
}
public void Expire(string id) public void Expire(string id)
{ {
if (m_LogLevel >= 2) if (m_LogLevel >= 2)
@ -807,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Asset
UuidGatherer gatherer = new UuidGatherer(m_AssetService); UuidGatherer gatherer = new UuidGatherer(m_AssetService);
HashSet<UUID> uniqueUuids = new HashSet<UUID>(); HashSet<UUID> uniqueUuids = new HashSet<UUID>();
Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>();
foreach (Scene s in m_Scenes) foreach (Scene s in m_Scenes)
{ {
@ -830,7 +794,7 @@ namespace OpenSim.Region.CoreModules.Asset
else if (storeUncached) else if (storeUncached)
{ {
AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
if (cachedAsset == null && assets[assetID] != AssetType.Unknown) if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
m_log.DebugFormat( m_log.DebugFormat(
"[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
@ -1067,11 +1031,6 @@ namespace OpenSim.Region.CoreModules.Asset
return asset.Data; return asset.Data;
} }
public bool CheckData(string id)
{
return Check(id); ;
}
public bool Get(string id, object sender, AssetRetrieved handler) public bool Get(string id, object sender, AssetRetrieved handler)
{ {
AssetBase asset = Get(id); AssetBase asset = Get(id);

View File

@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Asset
public bool Check(string id) public bool Check(string id)
{ {
return false; return m_Cache.Contains(id);
} }
public void Cache(AssetBase asset) public void Cache(AssetBase asset)

View File

@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
/// <value> /// <value>
/// Used to collect the uuids of the assets that we need to save into the archive /// Used to collect the uuids of the assets that we need to save into the archive
/// </value> /// </value>
protected Dictionary<UUID, AssetType> m_assetUuids = new Dictionary<UUID, AssetType>(); protected Dictionary<UUID, sbyte> m_assetUuids = new Dictionary<UUID, sbyte>();
/// <value> /// <value>
/// Used to collect the uuids of the users that we need to save into the archive /// Used to collect the uuids of the users that we need to save into the archive
@ -187,7 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// Don't chase down link asset items as they actually point to their target item IDs rather than an asset // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (sbyte)inventoryItem.AssetType, m_assetUuids);
} }
/// <summary> /// <summary>

View File

@ -1385,7 +1385,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos)
{ {
version = String.Empty; version = String.Empty;
newpos = new Vector3(pos.X, pos.Y, pos.Z); newpos = pos;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);

View File

@ -182,11 +182,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{ {
string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url); HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
uuidGatherer.GatherAssetUuids(so, ids); uuidGatherer.GatherAssetUuids(so, ids);
foreach (KeyValuePair<UUID, AssetType> kvp in ids) foreach (KeyValuePair<UUID, sbyte> kvp in ids)
uuidGatherer.FetchAsset(kvp.Key); uuidGatherer.FetchAsset(kvp.Key);
} }
} }

View File

@ -260,9 +260,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// The act of gathering UUIDs downloads some assets from the remote server // The act of gathering UUIDs downloads some assets from the remote server
// but not all... // but not all...
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids);
m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
bool success = true; bool success = true;
foreach (UUID uuid in ids.Keys) foreach (UUID uuid in ids.Keys)
@ -286,9 +286,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
if (asset != null) if (asset != null)
{ {
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids);
bool success = false; bool success = false;
foreach (UUID uuid in ids.Keys) foreach (UUID uuid in ids.Keys)
{ {

View File

@ -174,7 +174,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
#endregion #endregion
#region ISimulation #region ISimulationService
public IScene GetScene(UUID regionId) public IScene GetScene(UUID regionId)
{ {
@ -352,7 +352,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false; return false;
} }
#endregion /* IInterregionComms */ #endregion
#region Misc #region Misc

View File

@ -146,7 +146,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
#endregion #endregion
#region IInterregionComms #region ISimulationService
public IScene GetScene(UUID regionId) public IScene GetScene(UUID regionId)
{ {
@ -278,6 +278,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false; return false;
} }
#endregion /* IInterregionComms */ #endregion
} }
} }

View File

@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Archive the regions // Archive the regions
Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
scenesGroup.ForEachScene(delegate(Scene scene) scenesGroup.ForEachScene(delegate(Scene scene)
{ {
@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
} }
} }
private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids)
{ {
m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
@ -276,16 +276,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
RegionSettings regionSettings = scene.RegionInfo.RegionSettings; RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
Save(scene, sceneObjects, regionDir); Save(scene, sceneObjects, regionDir);
} }

View File

@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// <value> /// <value>
/// uuids to request /// uuids to request
/// </value> /// </value>
protected IDictionary<UUID, AssetType> m_uuids; protected IDictionary<UUID, sbyte> m_uuids;
/// <value> /// <value>
/// Callback used when all the assets requested have been received. /// Callback used when all the assets requested have been received.
@ -115,7 +115,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
protected Dictionary<string, object> m_options; protected Dictionary<string, object> m_options;
protected internal AssetsRequest( protected internal AssetsRequest(
AssetsArchiver assetsArchiver, IDictionary<UUID, AssetType> uuids, AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
IAssetService assetService, IUserAccountService userService, IAssetService assetService, IUserAccountService userService,
UUID scope, Dictionary<string, object> options, UUID scope, Dictionary<string, object> options,
AssetsRequestCallback assetsRequestCallback) AssetsRequestCallback assetsRequestCallback)
@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_requestCallbackTimer.Enabled = true; m_requestCallbackTimer.Enabled = true;
foreach (KeyValuePair<UUID, AssetType> kvp in m_uuids) foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
{ {
// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); // m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key);
@ -235,9 +235,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown) if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
{ {
AssetType type = (AssetType)assetType; m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, type); fetchedAsset.Type = (sbyte)assetType;
fetchedAsset.Type = (sbyte)type;
} }
AssetRequestCallback(fetchedAssetID, this, fetchedAsset); AssetRequestCallback(fetchedAssetID, this, fetchedAsset);

View File

@ -60,7 +60,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
public void Initialise() public void Initialise()
{ {
m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName); // m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName);
m_module.Scene.AddCommand("Regions", m_module, "set terrain texture", m_module.Scene.AddCommand("Regions", m_module, "set terrain texture",
"set terrain texture <number> <uuid> [<x>] [<y>]", "set terrain texture <number> <uuid> [<x>] [<y>]",

View File

@ -712,7 +712,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
} }
} }
public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
{ {
SceneObjectPart part; SceneObjectPart part;
@ -752,7 +752,9 @@ namespace OpenSim.Region.CoreModules.World.Estate
default: default:
break; break;
} }
SendTelehubInfo(client);
if (client != null)
SendTelehubInfo(client);
} }
private void SendSimulatorBlueBoxMessage( private void SendSimulatorBlueBoxMessage(
@ -1224,7 +1226,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; client.OnEstateRestartSimRequest += handleEstateRestartSimRequest;
client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest;
client.OnEstateChangeInfo += handleEstateChangeInfo; client.OnEstateChangeInfo += handleEstateChangeInfo;
client.OnEstateManageTelehub += handleOnEstateManageTelehub; client.OnEstateManageTelehub += HandleOnEstateManageTelehub;
client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest;
client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage;
client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage;

View File

@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
public struct DrawStruct public struct DrawStruct
{ {
public DrawRoutine dr; public DrawRoutine dr;
public Rectangle rect; // public Rectangle rect;
public SolidBrush brush; public SolidBrush brush;
public face[] trns; public face[] trns;
} }
@ -119,6 +119,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
{ {
mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID);
} }
return mapbmp; return mapbmp;
} }
@ -127,7 +128,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
try try
{ {
using (Bitmap mapbmp = CreateMapTile()) using (Bitmap mapbmp = CreateMapTile())
return OpenJPEG.EncodeFromImage(mapbmp, true); {
if (mapbmp != null)
return OpenJPEG.EncodeFromImage(mapbmp, true);
}
} }
catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke
{ {
@ -277,321 +281,331 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
tc = Environment.TickCount; tc = Environment.TickCount;
m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
EntityBase[] objs = whichScene.GetEntities(); EntityBase[] objs = whichScene.GetEntities();
Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
//SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
List<float> z_sortheights = new List<float>(); List<float> z_sortheights = new List<float>();
List<uint> z_localIDs = new List<uint>(); List<uint> z_localIDs = new List<uint>();
Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
lock (objs) try
{ {
foreach (EntityBase obj in objs) //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
lock (objs)
{ {
// Only draw the contents of SceneObjectGroup foreach (EntityBase obj in objs)
if (obj is SceneObjectGroup)
{ {
SceneObjectGroup mapdot = (SceneObjectGroup)obj; // Only draw the contents of SceneObjectGroup
Color mapdotspot = Color.Gray; // Default color when prim color is white if (obj is SceneObjectGroup)
// Loop over prim in group
foreach (SceneObjectPart part in mapdot.Parts)
{ {
if (part == null) SceneObjectGroup mapdot = (SceneObjectGroup)obj;
continue; Color mapdotspot = Color.Gray; // Default color when prim color is white
// Draw if the object is at least 1 meter wide in any direction // Loop over prim in group
if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) foreach (SceneObjectPart part in mapdot.Parts)
{ {
// Try to get the RGBA of the default texture entry.. if (part == null)
//
try
{
// get the null checks out of the way
// skip the ones that break
if (part == null)
continue;
if (part.Shape == null)
continue;
if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
continue; // eliminates trees from this since we don't really have a good tree representation
// if you want tree blocks on the map comment the above line and uncomment the below line
//mapdotspot = Color.PaleGreen;
Primitive.TextureEntry textureEntry = part.Shape.Textures;
if (textureEntry == null || textureEntry.DefaultTexture == null)
continue;
Color4 texcolor = textureEntry.DefaultTexture.RGBA;
// Not sure why some of these are null, oh well.
int colorr = 255 - (int)(texcolor.R * 255f);
int colorg = 255 - (int)(texcolor.G * 255f);
int colorb = 255 - (int)(texcolor.B * 255f);
if (!(colorr == 255 && colorg == 255 && colorb == 255))
{
//Try to set the map spot color
try
{
// If the color gets goofy somehow, skip it *shakes fist at Color4
mapdotspot = Color.FromArgb(colorr, colorg, colorb);
}
catch (ArgumentException)
{
}
}
}
catch (IndexOutOfRangeException)
{
// Windows Array
}
catch (ArgumentOutOfRangeException)
{
// Mono Array
}
Vector3 pos = part.GetWorldPosition();
// skip prim outside of retion
if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
continue; continue;
// skip prim in non-finite position // Draw if the object is at least 1 meter wide in any direction
if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) || if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
continue;
// Figure out if object is under 256m above the height of the terrain
bool isBelow256AboveTerrain = false;
try
{ {
isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f)); // Try to get the RGBA of the default texture entry..
} //
catch (Exception) try
{
}
if (isBelow256AboveTerrain)
{
// Translate scale by rotation so scale is represented properly when object is rotated
Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
Vector3 scale = new Vector3();
Vector3 tScale = new Vector3();
Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
Quaternion llrot = part.GetWorldRotation();
Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
scale = lscale * rot;
// negative scales don't work in this situation
scale.X = Math.Abs(scale.X);
scale.Y = Math.Abs(scale.Y);
scale.Z = Math.Abs(scale.Z);
// This scaling isn't very accurate and doesn't take into account the face rotation :P
int mapdrawstartX = (int)(pos.X - scale.X);
int mapdrawstartY = (int)(pos.Y - scale.Y);
int mapdrawendX = (int)(pos.X + scale.X);
int mapdrawendY = (int)(pos.Y + scale.Y);
// If object is beyond the edge of the map, don't draw it to avoid errors
if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
|| mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
|| mapdrawendY > ((int)Constants.RegionSize - 1))
continue;
#region obb face reconstruction part duex
Vector3[] vertexes = new Vector3[8];
// float[] distance = new float[6];
Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
scale = ((tScale * rot));
vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[0].x = pos.X + vertexes[0].x;
//vertexes[0].y = pos.Y + vertexes[0].y;
//vertexes[0].z = pos.Z + vertexes[0].z;
FaceA[0] = vertexes[0];
FaceB[3] = vertexes[0];
FaceA[4] = vertexes[0];
tScale = lscale;
scale = ((tScale * rot));
vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[1].x = pos.X + vertexes[1].x;
// vertexes[1].y = pos.Y + vertexes[1].y;
//vertexes[1].z = pos.Z + vertexes[1].z;
FaceB[0] = vertexes[1];
FaceA[1] = vertexes[1];
FaceC[4] = vertexes[1];
tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
//vertexes[2].x = pos.X + vertexes[2].x;
//vertexes[2].y = pos.Y + vertexes[2].y;
//vertexes[2].z = pos.Z + vertexes[2].z;
FaceC[0] = vertexes[2];
FaceD[3] = vertexes[2];
FaceC[5] = vertexes[2];
tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
//vertexes[3].x = pos.X + vertexes[3].x;
// vertexes[3].y = pos.Y + vertexes[3].y;
// vertexes[3].z = pos.Z + vertexes[3].z;
FaceD[0] = vertexes[3];
FaceC[1] = vertexes[3];
FaceA[5] = vertexes[3];
tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
scale = ((tScale * rot));
vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[4].x = pos.X + vertexes[4].x;
// vertexes[4].y = pos.Y + vertexes[4].y;
// vertexes[4].z = pos.Z + vertexes[4].z;
FaceB[1] = vertexes[4];
FaceA[2] = vertexes[4];
FaceD[4] = vertexes[4];
tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[5].x = pos.X + vertexes[5].x;
// vertexes[5].y = pos.Y + vertexes[5].y;
// vertexes[5].z = pos.Z + vertexes[5].z;
FaceD[1] = vertexes[5];
FaceC[2] = vertexes[5];
FaceB[5] = vertexes[5];
tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
scale = ((tScale * rot));
vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[6].x = pos.X + vertexes[6].x;
// vertexes[6].y = pos.Y + vertexes[6].y;
// vertexes[6].z = pos.Z + vertexes[6].z;
FaceB[2] = vertexes[6];
FaceA[3] = vertexes[6];
FaceB[4] = vertexes[6];
tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[7].x = pos.X + vertexes[7].x;
// vertexes[7].y = pos.Y + vertexes[7].y;
// vertexes[7].z = pos.Z + vertexes[7].z;
FaceD[2] = vertexes[7];
FaceC[3] = vertexes[7];
FaceD[5] = vertexes[7];
#endregion
//int wy = 0;
//bool breakYN = false; // If we run into an error drawing, break out of the
// loop so we don't lag to death on error handling
DrawStruct ds = new DrawStruct();
ds.brush = new SolidBrush(mapdotspot);
//ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
ds.trns = new face[FaceA.Length];
for (int i = 0; i < FaceA.Length; i++)
{ {
Point[] working = new Point[5]; // get the null checks out of the way
working[0] = project(FaceA[i], axPos); // skip the ones that break
working[1] = project(FaceB[i], axPos); if (part == null)
working[2] = project(FaceD[i], axPos); continue;
working[3] = project(FaceC[i], axPos);
working[4] = project(FaceA[i], axPos);
face workingface = new face(); if (part.Shape == null)
workingface.pts = working; continue;
ds.trns[i] = workingface; if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
continue; // eliminates trees from this since we don't really have a good tree representation
// if you want tree blocks on the map comment the above line and uncomment the below line
//mapdotspot = Color.PaleGreen;
Primitive.TextureEntry textureEntry = part.Shape.Textures;
if (textureEntry == null || textureEntry.DefaultTexture == null)
continue;
Color4 texcolor = textureEntry.DefaultTexture.RGBA;
// Not sure why some of these are null, oh well.
int colorr = 255 - (int)(texcolor.R * 255f);
int colorg = 255 - (int)(texcolor.G * 255f);
int colorb = 255 - (int)(texcolor.B * 255f);
if (!(colorr == 255 && colorg == 255 && colorb == 255))
{
//Try to set the map spot color
try
{
// If the color gets goofy somehow, skip it *shakes fist at Color4
mapdotspot = Color.FromArgb(colorr, colorg, colorb);
}
catch (ArgumentException)
{
}
}
}
catch (IndexOutOfRangeException)
{
// Windows Array
}
catch (ArgumentOutOfRangeException)
{
// Mono Array
} }
z_sort.Add(part.LocalId, ds); Vector3 pos = part.GetWorldPosition();
z_localIDs.Add(part.LocalId);
z_sortheights.Add(pos.Z);
//for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) // skip prim outside of retion
//{ if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
//for (wy = mapdrawstartY; wy < mapdrawendY; wy++) continue;
// skip prim in non-finite position
if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
continue;
// Figure out if object is under 256m above the height of the terrain
bool isBelow256AboveTerrain = false;
try
{
isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
}
catch (Exception)
{
}
if (isBelow256AboveTerrain)
{
// Translate scale by rotation so scale is represented properly when object is rotated
Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
Vector3 scale = new Vector3();
Vector3 tScale = new Vector3();
Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
Quaternion llrot = part.GetWorldRotation();
Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
scale = lscale * rot;
// negative scales don't work in this situation
scale.X = Math.Abs(scale.X);
scale.Y = Math.Abs(scale.Y);
scale.Z = Math.Abs(scale.Z);
// This scaling isn't very accurate and doesn't take into account the face rotation :P
int mapdrawstartX = (int)(pos.X - scale.X);
int mapdrawstartY = (int)(pos.Y - scale.Y);
int mapdrawendX = (int)(pos.X + scale.X);
int mapdrawendY = (int)(pos.Y + scale.Y);
// If object is beyond the edge of the map, don't draw it to avoid errors
if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
|| mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
|| mapdrawendY > ((int)Constants.RegionSize - 1))
continue;
#region obb face reconstruction part duex
Vector3[] vertexes = new Vector3[8];
// float[] distance = new float[6];
Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
scale = ((tScale * rot));
vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[0].x = pos.X + vertexes[0].x;
//vertexes[0].y = pos.Y + vertexes[0].y;
//vertexes[0].z = pos.Z + vertexes[0].z;
FaceA[0] = vertexes[0];
FaceB[3] = vertexes[0];
FaceA[4] = vertexes[0];
tScale = lscale;
scale = ((tScale * rot));
vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[1].x = pos.X + vertexes[1].x;
// vertexes[1].y = pos.Y + vertexes[1].y;
//vertexes[1].z = pos.Z + vertexes[1].z;
FaceB[0] = vertexes[1];
FaceA[1] = vertexes[1];
FaceC[4] = vertexes[1];
tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
//vertexes[2].x = pos.X + vertexes[2].x;
//vertexes[2].y = pos.Y + vertexes[2].y;
//vertexes[2].z = pos.Z + vertexes[2].z;
FaceC[0] = vertexes[2];
FaceD[3] = vertexes[2];
FaceC[5] = vertexes[2];
tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
//vertexes[3].x = pos.X + vertexes[3].x;
// vertexes[3].y = pos.Y + vertexes[3].y;
// vertexes[3].z = pos.Z + vertexes[3].z;
FaceD[0] = vertexes[3];
FaceC[1] = vertexes[3];
FaceA[5] = vertexes[3];
tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
scale = ((tScale * rot));
vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[4].x = pos.X + vertexes[4].x;
// vertexes[4].y = pos.Y + vertexes[4].y;
// vertexes[4].z = pos.Z + vertexes[4].z;
FaceB[1] = vertexes[4];
FaceA[2] = vertexes[4];
FaceD[4] = vertexes[4];
tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[5].x = pos.X + vertexes[5].x;
// vertexes[5].y = pos.Y + vertexes[5].y;
// vertexes[5].z = pos.Z + vertexes[5].z;
FaceD[1] = vertexes[5];
FaceC[2] = vertexes[5];
FaceB[5] = vertexes[5];
tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
scale = ((tScale * rot));
vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[6].x = pos.X + vertexes[6].x;
// vertexes[6].y = pos.Y + vertexes[6].y;
// vertexes[6].z = pos.Z + vertexes[6].z;
FaceB[2] = vertexes[6];
FaceA[3] = vertexes[6];
FaceB[4] = vertexes[6];
tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
scale = ((tScale * rot));
vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
// vertexes[7].x = pos.X + vertexes[7].x;
// vertexes[7].y = pos.Y + vertexes[7].y;
// vertexes[7].z = pos.Z + vertexes[7].z;
FaceD[2] = vertexes[7];
FaceC[3] = vertexes[7];
FaceD[5] = vertexes[7];
#endregion
//int wy = 0;
//bool breakYN = false; // If we run into an error drawing, break out of the
// loop so we don't lag to death on error handling
DrawStruct ds = new DrawStruct();
ds.brush = new SolidBrush(mapdotspot);
//ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
ds.trns = new face[FaceA.Length];
for (int i = 0; i < FaceA.Length; i++)
{
Point[] working = new Point[5];
working[0] = project(FaceA[i], axPos);
working[1] = project(FaceB[i], axPos);
working[2] = project(FaceD[i], axPos);
working[3] = project(FaceC[i], axPos);
working[4] = project(FaceA[i], axPos);
face workingface = new face();
workingface.pts = working;
ds.trns[i] = workingface;
}
z_sort.Add(part.LocalId, ds);
z_localIDs.Add(part.LocalId);
z_sortheights.Add(pos.Z);
//for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
//{ //{
//m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
//try
//{ //{
// Remember, flip the y! //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
// mapbmp.SetPixel(wx, (255 - wy), mapdotspot); //try
//} //{
//catch (ArgumentException) // Remember, flip the y!
//{ // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
// breakYN = true; //}
//catch (ArgumentException)
//{
// breakYN = true;
//}
//if (breakYN)
// break;
//} //}
//if (breakYN) //if (breakYN)
// break; // break;
//} //}
} // Object is within 256m Z of terrain
} // object is at least a meter wide
} // loop over group children
} // entitybase is sceneobject group
} // foreach loop over entities
//if (breakYN) float[] sortedZHeights = z_sortheights.ToArray();
// break; uint[] sortedlocalIds = z_localIDs.ToArray();
//}
} // Object is within 256m Z of terrain
} // object is at least a meter wide
} // loop over group children
} // entitybase is sceneobject group
} // foreach loop over entities
float[] sortedZHeights = z_sortheights.ToArray(); // Sort prim by Z position
uint[] sortedlocalIds = z_localIDs.ToArray(); Array.Sort(sortedZHeights, sortedlocalIds);
// Sort prim by Z position using (Graphics g = Graphics.FromImage(mapbmp))
Array.Sort(sortedZHeights, sortedlocalIds);
Graphics g = Graphics.FromImage(mapbmp);
for (int s = 0; s < sortedZHeights.Length; s++)
{
if (z_sort.ContainsKey(sortedlocalIds[s]))
{ {
DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; for (int s = 0; s < sortedZHeights.Length; s++)
for (int r = 0; r < rectDrawStruct.trns.Length; r++)
{ {
g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); if (z_sort.ContainsKey(sortedlocalIds[s]))
{
DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]];
for (int r = 0; r < rectDrawStruct.trns.Length; r++)
{
g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts);
}
//g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
}
} }
//g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
} }
} } // lock entities objs
g.Dispose(); }
} // lock entities objs finally
{
foreach (DrawStruct ds in z_sort.Values)
ds.brush.Dispose();
}
m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms"); m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms");
return mapbmp; return mapbmp;
} }

View File

@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
public void TerrainToBitmap(Bitmap mapbmp) public void TerrainToBitmap(Bitmap mapbmp)
{ {
int tc = Environment.TickCount; int tc = Environment.TickCount;
m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
double[,] hm = m_scene.Heightmap.GetDoubles(); double[,] hm = m_scene.Heightmap.GetDoubles();
bool ShadowDebugContinue = true; bool ShadowDebugContinue = true;
@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
{ {
if (!terraincorruptedwarningsaid) if (!terraincorruptedwarningsaid)
{ {
m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
terraincorruptedwarningsaid = true; terraincorruptedwarningsaid = true;
} }
color = Color.Black; color = Color.Black;
@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
{ {
if (!terraincorruptedwarningsaid) if (!terraincorruptedwarningsaid)
{ {
m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
terraincorruptedwarningsaid = true; terraincorruptedwarningsaid = true;
} }
Color black = Color.Black; Color black = Color.Black;
@ -238,7 +238,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
} }
} }
} }
m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
} }
} }
} }

View File

@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
private Bitmap fetchTexture(UUID id) private Bitmap fetchTexture(UUID id)
{ {
AssetBase asset = m_scene.AssetService.Get(id.ToString()); AssetBase asset = m_scene.AssetService.Get(id.ToString());
m_log.DebugFormat("[TexturedMapTileRenderer]: Fetched texture {0}, found: {1}", id, asset != null); m_log.DebugFormat("[TEXTURED MAP TILE RENDERER]: Fetched texture {0}, found: {1}", id, asset != null);
if (asset == null) return null; if (asset == null) return null;
ManagedImage managedImage; ManagedImage managedImage;
@ -188,17 +188,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
} }
catch (DllNotFoundException) catch (DllNotFoundException)
{ {
m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id); m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id);
} }
catch (IndexOutOfRangeException) catch (IndexOutOfRangeException)
{ {
m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
} }
catch (Exception) catch (Exception)
{ {
m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
} }
return null; return null;
@ -233,10 +233,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
if (textureID == UUID.Zero) return defaultColor; // not set if (textureID == UUID.Zero) return defaultColor; // not set
if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures
Bitmap bmp = fetchTexture(textureID); Color color;
Color color = bmp == null ? defaultColor : computeAverageColor(bmp);
// store it for future reference using (Bitmap bmp = fetchTexture(textureID))
m_mapping[textureID] = color; {
color = bmp == null ? defaultColor : computeAverageColor(bmp);
// store it for future reference
m_mapping[textureID] = color;
}
return color; return color;
} }
@ -278,7 +282,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
public void TerrainToBitmap(Bitmap mapbmp) public void TerrainToBitmap(Bitmap mapbmp)
{ {
int tc = Environment.TickCount; int tc = Environment.TickCount;
m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
// These textures should be in the AssetCache anyway, as every client conneting to this // These textures should be in the AssetCache anyway, as every client conneting to this
// region needs them. Except on start, when the map is recreated (before anyone connected), // region needs them. Except on start, when the map is recreated (before anyone connected),
@ -412,7 +416,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
} }
} }
} }
m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
} }
} }
} }

View File

@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
"export-map [<path>]", "export-map [<path>]",
"Save an image of the world map", HandleExportWorldMapConsoleCommand); "Save an image of the world map", HandleExportWorldMapConsoleCommand);
m_scene.AddCommand(
"Regions", this, "generate map",
"generate map",
"Generates and stores a new maptile.", HandleGenerateMapConsoleCommand);
AddHandlers(); AddHandlers();
} }
} }
@ -1324,6 +1329,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
m_scene.RegionInfo.RegionName, exportPath); m_scene.RegionInfo.RegionName, exportPath);
} }
public void HandleGenerateMapConsoleCommand(string module, string[] cmdparams)
{
Scene consoleScene = m_scene.ConsoleScene();
if (consoleScene != null && consoleScene != m_scene)
return;
GenerateMaptile();
}
public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
{ {
uint xstart = 0; uint xstart = 0;
@ -1561,88 +1576,69 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
private Byte[] GenerateOverlay() private Byte[] GenerateOverlay()
{ {
Bitmap overlay = new Bitmap(256, 256); using (Bitmap overlay = new Bitmap(256, 256))
bool[,] saleBitmap = new bool[64, 64];
for (int x = 0 ; x < 64 ; x++)
{ {
for (int y = 0 ; y < 64 ; y++) bool[,] saleBitmap = new bool[64, 64];
saleBitmap[x, y] = false; for (int x = 0 ; x < 64 ; x++)
}
bool landForSale = false;
List<ILandObject> parcels = m_scene.LandChannel.AllParcels();
Color background = Color.FromArgb(0, 0, 0, 0);
SolidBrush transparent = new SolidBrush(background);
Graphics g = Graphics.FromImage(overlay);
g.FillRectangle(transparent, 0, 0, 255, 255);
SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9));
Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
foreach (ILandObject land in parcels)
{
// m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
{ {
landForSale = true; for (int y = 0 ; y < 64 ; y++)
saleBitmap[x, y] = false;
bool[,] landBitmap = land.GetLandBitmap(); }
for (int x = 0 ; x < 64 ; x++) bool landForSale = false;
List<ILandObject> parcels = m_scene.LandChannel.AllParcels();
Color background = Color.FromArgb(0, 0, 0, 0);
using (Graphics g = Graphics.FromImage(overlay))
{
using (SolidBrush transparent = new SolidBrush(background))
g.FillRectangle(transparent, 0, 0, 256, 256);
foreach (ILandObject land in parcels)
{ {
for (int y = 0 ; y < 64 ; y++) // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
{ {
if (landBitmap[x, y]) landForSale = true;
{
g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
if (x > 0) saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
{
if ((saleBitmap[x - 1, y] || landBitmap[x - 1, y]) == false)
g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4, 255 - (y * 4));
}
if (y > 0)
{
if ((saleBitmap[x, y-1] || landBitmap[x, y-1]) == false)
g.DrawLine(grey, x * 4, 255 - (y * 4), x * 4 + 3, 255 - (y * 4));
}
if (x < 63)
{
if ((saleBitmap[x + 1, y] || landBitmap[x + 1, y]) == false)
g.DrawLine(grey, x * 4 + 3, 252 - (y * 4), x * 4 + 3, 255 - (y * 4));
}
if (y < 63)
{
if ((saleBitmap[x, y + 1] || landBitmap[x, y + 1]) == false)
g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4 + 3, 252 - (y * 4));
}
}
} }
} }
saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap); if (!landForSale)
{
m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
return null;
}
m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)))
{
for (int x = 0 ; x < 64 ; x++)
{
for (int y = 0 ; y < 64 ; y++)
{
if (saleBitmap[x, y])
g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
}
}
}
}
try
{
return OpenJPEG.EncodeFromImage(overlay, true);
}
catch (Exception e)
{
m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
} }
} }
if (!landForSale)
{
m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
return null;
}
m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
try
{
return OpenJPEG.EncodeFromImage(overlay, true);
}
catch (Exception e)
{
m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
}
return null; return null;
} }
} }

View File

@ -47,13 +47,33 @@ namespace OpenSim.Region.Framework.Interfaces
/// The handle of the destination region. If it's the same as the region currently /// The handle of the destination region. If it's the same as the region currently
/// occupied by the agent then the teleport will be within that region. /// occupied by the agent then the teleport will be within that region.
/// </param> /// </param>
/// <param name='agent'></param>
/// <param name='regionHandle'></param>
/// <param name='position'></param> /// <param name='position'></param>
/// <param name='lookAt'></param> /// <param name='lookAt'></param>
/// <param name='teleportFlags'></param> /// <param name='teleportFlags'></param>
void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
/// <summary>
/// Teleports the agent for the given client to their home destination.
/// </summary>
/// <param name='id'></param>
/// <param name='client'></param>
bool TeleportHome(UUID id, IClientAPI client); bool TeleportHome(UUID id, IClientAPI client);
/// <summary>
/// Teleport an agent directly to a given region without checking whether the region should be substituted.
/// </summary>
/// <remarks>
/// Please use Teleport() instead unless you know exactly what you're doing.
/// Do not use for same region teleports.
/// </remarks>
/// <param name='sp'></param>
/// <param name='reg'></param>
/// <param name='finalDestination'>/param>
/// <param name='position'></param>
/// <param name='lookAt'></param>
/// <param name='teleportFlags'></param>
void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
Vector3 position, Vector3 lookAt, uint teleportFlags); Vector3 position, Vector3 lookAt, uint teleportFlags);

View File

@ -1,119 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the 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 OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
public delegate bool ChildAgentUpdateReceived(AgentData data);
public interface IInterregionCommsOut
{
#region Agents
bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit, uint teleportFlags, out string reason);
/// <summary>
/// Full child agent update.
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="data"></param>
/// <returns></returns>
bool SendChildAgentUpdate(ulong regionHandle, AgentData data);
/// <summary>
/// Short child agent update, mostly for position.
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="data"></param>
/// <returns></returns>
bool SendChildAgentUpdate(ulong regionHandle, AgentPosition data);
bool SendRetrieveRootAgent(ulong regionHandle, UUID id, out IAgentData agent);
/// <summary>
/// Message from receiving region to departing region, telling it got contacted by the client.
/// When sent over REST, it invokes the opaque uri.
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="id"></param>
/// <param name="uri"></param>
/// <returns></returns>
bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
/// <summary>
/// Close chid agent.
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="id"></param>
/// <returns></returns>
bool SendCloseChildAgent(ulong regionHandle, UUID id);
/// <summary>
/// Close agent.
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="id"></param>
/// <returns></returns>
bool SendCloseAgent(ulong regionHandle, UUID id);
#endregion Agents
#region Objects
/// <summary>
/// Create an object in the destination region. This message is used primarily for prim crossing.
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="sog"></param>
/// <param name="isLocalCall"></param>
/// <returns></returns>
bool SendCreateObject(ulong regionHandle, SceneObjectGroup sog, bool isLocalCall);
/// <summary>
/// Create an object from the user's inventory in the destination region.
/// This message is used primarily by clients.
/// </summary>
/// <param name="regionHandle"></param>
/// <param name="userID"></param>
/// <param name="itemID"></param>
/// <returns></returns>
bool SendCreateObject(ulong regionHandle, UUID userID, UUID itemID);
#endregion Objects
}
// This may not be needed, but having it here for now.
public interface IInterregionCommsIn
{
event ChildAgentUpdateReceived OnChildAgentUpdate;
}
}

View File

@ -51,10 +51,17 @@ namespace OpenSim.Region.Framework.Interfaces
UUID = 5 UUID = 5
} }
public struct JsonStoreStats
{
public int StoreCount;
}
public delegate void TakeValueCallback(string s); public delegate void TakeValueCallback(string s);
public interface IJsonStoreModule public interface IJsonStoreModule
{ {
JsonStoreStats GetStoreStats();
bool AttachObjectStore(UUID objectID); bool AttachObjectStore(UUID objectID);
bool CreateStore(string value, ref UUID result); bool CreateStore(string value, ref UUID result);
bool DestroyStore(UUID storeID); bool DestroyStore(UUID storeID);

View File

@ -4121,32 +4121,52 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
// m_log.DebugFormat(
// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
// Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
RegionInfo.EstateSettings.AllowDirectTeleport == false && RegionInfo.EstateSettings.AllowDirectTeleport == false &&
!viahome && !godlike) !viahome && !godlike)
{ {
SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
// Can have multiple SpawnPoints
List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); if (telehub != null)
if (spawnpoints.Count > 1)
{ {
// We have multiple SpawnPoints, Route the agent to a random or sequential one // Can have multiple SpawnPoints
if (SpawnPointRouting == "random") List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( if (spawnpoints.Count > 1)
telehub.AbsolutePosition, {
telehub.GroupRotation // We have multiple SpawnPoints, Route the agent to a random or sequential one
); if (SpawnPointRouting == "random")
acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
telehub.AbsolutePosition,
telehub.GroupRotation
);
else
acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
telehub.AbsolutePosition,
telehub.GroupRotation
);
}
else if (spawnpoints.Count == 1)
{
// We have a single SpawnPoint and will route the agent to it
acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
}
else else
acd.startpos = spawnpoints[SpawnPoint()].GetLocation( {
telehub.AbsolutePosition, m_log.DebugFormat(
telehub.GroupRotation "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
); RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
}
} }
else else
{ {
// We have a single SpawnPoint and will route the agent to it m_log.DebugFormat(
acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
} }
return true; return true;
@ -4593,18 +4613,6 @@ namespace OpenSim.Region.Framework.Scenes
return sp; return sp;
} }
public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent)
{
agent = null;
ScenePresence sp = GetScenePresence(id);
if ((sp != null) && (!sp.IsChildAgent))
{
sp.IsChildAgent = true;
return sp.CopyAgent(out agent);
}
return false;
}
/// <summary> /// <summary>
/// Authenticated close (via network) /// Authenticated close (via network)
/// </summary> /// </summary>

View File

@ -109,6 +109,16 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
/// the viewer fires these in quick succession.
/// </summary>
/// <remarks>
/// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
/// regulation done there.
/// </remarks>
private object m_completeMovementLock = new object();
// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); // private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@ -984,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Turns a child agent into a root agent. /// Turns a child agent into a root agent.
/// </summary> /// </summary>
/// <remarks>
/// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
/// avatar is actual in the sim. They can perform all actions. /// avatar is actual in the sim. They can perform all actions.
/// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@ -991,48 +1002,51 @@ namespace OpenSim.Region.Framework.Scenes
/// ///
/// This method is on the critical path for transferring an avatar from one region to another. Delay here /// This method is on the critical path for transferring an avatar from one region to another. Delay here
/// delays that crossing. /// delays that crossing.
/// </summary> /// </remarks>
private void MakeRootAgent(Vector3 pos, bool isFlying) private bool MakeRootAgent(Vector3 pos, bool isFlying)
{ {
// m_log.InfoFormat( lock (m_completeMovementLock)
// "[SCENE]: Upgrading child to root agent for {0} in {1}",
// Name, m_scene.RegionInfo.RegionName);
if (ParentUUID != UUID.Zero)
{ {
m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); if (!IsChildAgent)
SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); return false;
if (part == null)
//m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
// m_log.InfoFormat(
// "[SCENE]: Upgrading child to root agent for {0} in {1}",
// Name, m_scene.RegionInfo.RegionName);
if (ParentUUID != UUID.Zero)
{ {
m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
if (part == null)
{
m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
}
else
{
part.ParentGroup.AddAvatar(UUID);
if (part.SitTargetPosition != Vector3.Zero)
part.SitTargetAvatar = UUID;
// ParentPosition = part.GetWorldPosition();
ParentID = part.LocalId;
ParentPart = part;
m_pos = PrevSitOffset;
// pos = ParentPosition;
pos = part.GetWorldPosition();
}
ParentUUID = UUID.Zero;
// Animator.TrySetMovementAnimation("SIT");
} }
else else
{ {
part.ParentGroup.AddAvatar(UUID); IsLoggingIn = false;
if (part.SitTargetPosition != Vector3.Zero)
part.SitTargetAvatar = UUID;
// ParentPosition = part.GetWorldPosition();
ParentID = part.LocalId;
ParentPart = part;
m_pos = PrevSitOffset;
// pos = ParentPosition;
pos = part.GetWorldPosition();
} }
ParentUUID = UUID.Zero;
IsChildAgent = false; IsChildAgent = false;
// Animator.TrySetMovementAnimation("SIT");
} }
else
{
IsChildAgent = false;
IsLoggingIn = false;
}
//m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
IsChildAgent = false;
// Must reset this here so that a teleport to a region next to an existing region does not keep the flag // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
// set and prevent the close of the connection on a subsequent re-teleport. // set and prevent the close of the connection on a subsequent re-teleport.
@ -1178,22 +1192,36 @@ namespace OpenSim.Region.Framework.Scenes
// and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
// be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
// not transporting the required data. // not transporting the required data.
lock (m_attachments) //
{ // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
if (HasAttachments()) // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
{ // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
m_log.DebugFormat( // not transporting the required data.
"[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); //
// We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
// the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
// which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
//
// FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
// But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
// is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
// script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
//
// One cannot simply iterate over attachments in a fire and forget thread because this would no longer
// be locked, allowing race conditions if other code changes the attachments list.
List<SceneObjectGroup> attachments = GetAttachments();
// Resume scripts if (attachments.Count > 0)
Util.FireAndForget(delegate(object x) { {
foreach (SceneObjectGroup sog in m_attachments) m_log.DebugFormat(
{ "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
sog.ScheduleGroupForFullUpdate();
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); // Resume scripts
sog.ResumeScripts(); foreach (SceneObjectGroup sog in attachments)
} {
}); sog.ScheduleGroupForFullUpdate();
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
sog.ResumeScripts();
} }
} }
} }
@ -1215,6 +1243,7 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.EventManager.TriggerOnMakeRootAgent(this); m_scene.EventManager.TriggerOnMakeRootAgent(this);
return true;
} }
public int GetStateSource() public int GetStateSource()
@ -1637,7 +1666,14 @@ namespace OpenSim.Region.Framework.Scenes
} }
bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
MakeRootAgent(AbsolutePosition, flying); if (!MakeRootAgent(AbsolutePosition, flying))
{
m_log.DebugFormat(
"[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
Name, Scene.Name);
return;
}
// Tell the client that we're totally ready // Tell the client that we're totally ready
ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
@ -2884,7 +2920,6 @@ namespace OpenSim.Region.Framework.Scenes
Rotation = newRot; Rotation = newRot;
// ParentPosition = part.AbsolutePosition; // ParentPosition = part.AbsolutePosition;
part.ParentGroup.AddAvatar(UUID);
} }
else else
{ {
@ -2893,13 +2928,13 @@ namespace OpenSim.Region.Framework.Scenes
m_pos -= part.GroupPosition; m_pos -= part.GroupPosition;
// ParentPosition = part.AbsolutePosition; // ParentPosition = part.AbsolutePosition;
part.ParentGroup.AddAvatar(UUID);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
} }
part.ParentGroup.AddAvatar(UUID);
ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
ParentID = m_requestedSitTargetID; ParentID = m_requestedSitTargetID;
m_AngularVelocity = Vector3.Zero; m_AngularVelocity = Vector3.Zero;
@ -3210,6 +3245,8 @@ namespace OpenSim.Region.Framework.Scenes
// again here... this comes after the cached appearance check because the avatars // again here... this comes after the cached appearance check because the avatars
// appearance goes into the avatar update packet // appearance goes into the avatar update packet
SendAvatarDataToAllAgents(); SendAvatarDataToAllAgents();
// This invocation always shows up in the viewer logs as an error. Is it needed?
SendAppearanceToAgent(this); SendAppearanceToAgent(this);
// If we are using the the cached appearance then send it out to everyone // If we are using the the cached appearance then send it out to everyone

View File

@ -111,6 +111,45 @@ namespace OpenSim.Region.Framework.Scenes.Tests
Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
} }
/// <summary>
/// Test that duplicate complete movement calls are ignored.
/// </summary>
/// <remarks>
/// If duplicate calls are not ignored then there is a risk of race conditions or other unexpected effects.
/// </remarks>
[Test]
public void TestDupeCompleteMovementCalls()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID spUuid = TestHelpers.ParseTail(0x1);
TestScene scene = new SceneHelpers().SetupScene();
int makeRootAgentEvents = 0;
scene.EventManager.OnMakeRootAgent += spi => makeRootAgentEvents++;
ScenePresence sp = SceneHelpers.AddScenePresence(scene, spUuid);
Assert.That(makeRootAgentEvents, Is.EqualTo(1));
// Normally these would be invoked by a CompleteMovement message coming in to the UDP stack. But for
// convenience, here we will invoke it manually.
sp.CompleteMovement(sp.ControllingClient, true);
Assert.That(makeRootAgentEvents, Is.EqualTo(1));
// Check rest of exepcted parameters.
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
Assert.That(sp.IsChildAgent, Is.False);
Assert.That(sp.UUID, Is.EqualTo(spUuid));
Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
}
[Test] [Test]
public void TestCreateDuplicateRootScenePresence() public void TestCreateDuplicateRootScenePresence()
{ {
@ -249,58 +288,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
// Assert.That(childPresence, Is.Not.Null); // Assert.That(childPresence, Is.Not.Null);
// Assert.That(childPresence.IsChildAgent, Is.True); // Assert.That(childPresence.IsChildAgent, Is.True);
} }
// /// <summary>
// /// Test adding a root agent to a scene. Doesn't yet actually complete crossing the agent into the scene.
// /// </summary>
// [Test]
// public void T010_TestAddRootAgent()
// {
// TestHelpers.InMethod();
//
// string firstName = "testfirstname";
//
// AgentCircuitData agent = new AgentCircuitData();
// agent.AgentID = agent1;
// agent.firstname = firstName;
// agent.lastname = "testlastname";
// agent.SessionID = UUID.Random();
// agent.SecureSessionID = UUID.Random();
// agent.circuitcode = 123;
// agent.BaseFolder = UUID.Zero;
// agent.InventoryFolder = UUID.Zero;
// agent.startpos = Vector3.Zero;
// agent.CapsPath = GetRandomCapsObjectPath();
// agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
// agent.child = true;
//
// scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
//
// string reason;
// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason);
// testclient = new TestClient(agent, scene);
// scene.AddNewAgent(testclient);
//
// ScenePresence presence = scene.GetScenePresence(agent1);
//
// Assert.That(presence, Is.Not.Null, "presence is null");
// Assert.That(presence.Firstname, Is.EqualTo(firstName), "First name not same");
// acd1 = agent;
// }
//
// /// <summary>
// /// Test removing an uncrossed root agent from a scene.
// /// </summary>
// [Test]
// public void T011_TestRemoveRootAgent()
// {
// TestHelpers.InMethod();
//
// scene.RemoveClient(agent1);
//
// ScenePresence presence = scene.GetScenePresence(agent1);
//
// Assert.That(presence, Is.Null, "presence is not null");
// }
} }
} }

View File

@ -0,0 +1,119 @@
/*
* 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 Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.World.Estate;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.Framework.Scenes.Tests
{
/// <summary>
/// Scene telehub tests
/// </summary>
/// <remarks>
/// TODO: Tests which run through normal functionality. Currently, the only test is one that checks behaviour
/// in the case of an error condition
/// </remarks>
[TestFixture]
public class SceneTelehubTests : OpenSimTestCase
{
/// <summary>
/// Test for desired behaviour when a telehub has no spawn points
/// </summary>
[Test]
public void TestNoTelehubSpawnPoints()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
EstateManagementModule emm = new EstateManagementModule();
SceneHelpers sh = new SceneHelpers();
Scene scene = sh.SetupScene();
SceneHelpers.SetupSceneModules(scene, emm);
UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
// Must still be possible to successfully log in
UUID loggingInUserId = TestHelpers.ParseTail(0x2);
UserAccount ua
= UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
SceneHelpers.AddScenePresence(scene, ua);
Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
}
/// <summary>
/// Test for desired behaviour when the scene object nominated as a telehub object does not exist.
/// </summary>
[Test]
public void TestNoTelehubSceneObject()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
EstateManagementModule emm = new EstateManagementModule();
SceneHelpers sh = new SceneHelpers();
Scene scene = sh.SetupScene();
SceneHelpers.SetupSceneModules(scene, emm);
UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
SceneObjectGroup spawnPointSo = SceneHelpers.AddSceneObject(scene, "spawnpointObject", telehubSceneObjectOwner);
emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "spawnpoint add", spawnPointSo.LocalId);
scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
scene.DeleteSceneObject(telehubSo, false);
// Must still be possible to successfully log in
UUID loggingInUserId = TestHelpers.ParseTail(0x2);
UserAccount ua
= UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
SceneHelpers.AddScenePresence(scene, ua);
Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
}
}
}

View File

@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
= AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
m_assetService.Store(corruptAsset); m_assetService.Store(corruptAsset);
IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
// We count the uuid as gathered even if the asset itself is corrupt. // We count the uuid as gathered even if the asset itself is corrupt.
Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
// We count the uuid as gathered even if the asset itself is missing. // We count the uuid as gathered even if the asset itself is missing.
Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
m_assetService.Store(ncAsset); m_assetService.Store(ncAsset);
IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
// We count the uuid as gathered even if the asset itself is corrupt. // We count the uuid as gathered even if the asset itself is corrupt.
Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); Assert.That(foundAssetUuids.Count, Is.EqualTo(2));

View File

@ -38,6 +38,7 @@ using OpenMetaverse.StructuredData;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
namespace OpenSim.Region.Framework.Scenes namespace OpenSim.Region.Framework.Scenes
{ {
@ -83,29 +84,33 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
/// <param name="assetType">The type of the asset for the uuid given</param> /// <param name="assetType">The type of the asset for the uuid given</param>
/// <param name="assetUuids">The assets gathered</param> /// <param name="assetUuids">The assets gathered</param>
public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
{ {
try try
{ {
assetUuids[assetUuid] = assetType; assetUuids[assetUuid] = assetType;
if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
{ {
GetWearableAssetUuids(assetUuid, assetUuids); GetWearableAssetUuids(assetUuid, assetUuids);
} }
else if (AssetType.Gesture == assetType) else if ((sbyte)AssetType.Gesture == assetType)
{ {
GetGestureAssetUuids(assetUuid, assetUuids); GetGestureAssetUuids(assetUuid, assetUuids);
} }
else if (AssetType.Notecard == assetType) else if ((sbyte)AssetType.Notecard == assetType)
{ {
GetTextEmbeddedAssetUuids(assetUuid, assetUuids); GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
} }
else if (AssetType.LSLText == assetType) else if ((sbyte)AssetType.LSLText == assetType)
{ {
GetTextEmbeddedAssetUuids(assetUuid, assetUuids); GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
} }
else if (AssetType.Object == assetType) else if ((sbyte)OpenSimAssetType.Material == assetType)
{
GetMaterialAssetUuids(assetUuid, assetUuids);
}
else if ((sbyte)AssetType.Object == assetType)
{ {
GetSceneObjectAssetUuids(assetUuid, assetUuids); GetSceneObjectAssetUuids(assetUuid, assetUuids);
} }
@ -132,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
/// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
/// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
/// </param> /// </param>
public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@ -152,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// Get the prim's default texture. This will be used for faces which don't have their own texture // Get the prim's default texture. This will be used for faces which don't have their own texture
if (textureEntry.DefaultTexture != null) if (textureEntry.DefaultTexture != null)
assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
if (textureEntry.FaceTextures != null) if (textureEntry.FaceTextures != null)
{ {
@ -160,20 +165,20 @@ namespace OpenSim.Region.Framework.Scenes
foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
{ {
if (texture != null) if (texture != null)
assetUuids[texture.TextureID] = AssetType.Texture; assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
} }
} }
} }
// If the prim is a sculpt then preserve this information too // If the prim is a sculpt then preserve this information too
if (part.Shape.SculptTexture != UUID.Zero) if (part.Shape.SculptTexture != UUID.Zero)
assetUuids[part.Shape.SculptTexture] = AssetType.Texture; assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
if (part.Shape.ProjectionTextureUUID != UUID.Zero) if (part.Shape.ProjectionTextureUUID != UUID.Zero)
assetUuids[part.Shape.ProjectionTextureUUID] = AssetType.Texture; assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
if (part.CollisionSound != UUID.Zero) if (part.CollisionSound != UUID.Zero)
assetUuids[part.CollisionSound] = AssetType.Sound; assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
if (part.ParticleSystem.Length > 0) if (part.ParticleSystem.Length > 0)
{ {
@ -181,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
if (ps.Texture != UUID.Zero) if (ps.Texture != UUID.Zero)
assetUuids[ps.Texture] = AssetType.Texture; assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
} }
catch (Exception e) catch (Exception e)
{ {
@ -201,7 +206,7 @@ namespace OpenSim.Region.Framework.Scenes
// tii.Name, tii.Type, part.Name, part.UUID); // tii.Name, tii.Type, part.Name, part.UUID);
if (!assetUuids.ContainsKey(tii.AssetID)) if (!assetUuids.ContainsKey(tii.AssetID))
GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
} }
// FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
@ -210,7 +215,9 @@ namespace OpenSim.Region.Framework.Scenes
// Scene.EventManager is present. // Scene.EventManager is present.
// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
GatherMaterialsUuids(part, assetUuids);
// still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
GatherMaterialsUuids(part, assetUuids);
} }
catch (Exception e) catch (Exception e)
{ {
@ -221,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
// /// <summary> // /// <summary>
// /// The callback made when we request the asset for an object from the asset service. // /// The callback made when we request the asset for an object from the asset service.
// /// </summary> // /// </summary>
@ -237,10 +244,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
/// stored in legacy format in part.DynAttrs
/// </summary> /// </summary>
/// <param name="part"></param> /// <param name="part"></param>
/// <param name="assetUuids"></param> /// <param name="assetUuids"></param>
public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids) //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids)
{ {
// scan thru the dynAttrs map of this part for any textures used as materials // scan thru the dynAttrs map of this part for any textures used as materials
OSD osdMaterials = null; OSD osdMaterials = null;
@ -276,7 +285,7 @@ namespace OpenSim.Region.Framework.Scenes
UUID normalMapId = mat["NormMap"].AsUUID(); UUID normalMapId = mat["NormMap"].AsUUID();
if (normalMapId != UUID.Zero) if (normalMapId != UUID.Zero)
{ {
assetUuids[normalMapId] = AssetType.Texture; assetUuids[normalMapId] = (sbyte)AssetType.Texture;
//m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
} }
} }
@ -285,7 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
UUID specularMapId = mat["SpecMap"].AsUUID(); UUID specularMapId = mat["SpecMap"].AsUUID();
if (specularMapId != UUID.Zero) if (specularMapId != UUID.Zero)
{ {
assetUuids[specularMapId] = AssetType.Texture; assetUuids[specularMapId] = (sbyte)AssetType.Texture;
//m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
} }
} }
@ -340,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
/// <param name="scriptUuid"></param> /// <param name="scriptUuid"></param>
/// <param name="assetUuids">Dictionary in which to record the references</param> /// <param name="assetUuids">Dictionary in which to record the references</param>
private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
{ {
// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
@ -360,7 +369,7 @@ namespace OpenSim.Region.Framework.Scenes
// Embedded asset references (if not false positives) could be for many types of asset, so we will // Embedded asset references (if not false positives) could be for many types of asset, so we will
// label these as unknown. // label these as unknown.
assetUuids[uuid] = AssetType.Unknown; assetUuids[uuid] = (sbyte)AssetType.Unknown;
} }
} }
} }
@ -370,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
/// <param name="wearableAssetUuid"></param> /// <param name="wearableAssetUuid"></param>
/// <param name="assetUuids">Dictionary in which to record the references</param> /// <param name="assetUuids">Dictionary in which to record the references</param>
private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
{ {
AssetBase assetBase = GetAsset(wearableAssetUuid); AssetBase assetBase = GetAsset(wearableAssetUuid);
@ -385,7 +394,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (UUID uuid in wearableAsset.Textures.Values) foreach (UUID uuid in wearableAsset.Textures.Values)
{ {
assetUuids[uuid] = AssetType.Texture; assetUuids[uuid] = (sbyte)AssetType.Texture;
} }
} }
} }
@ -397,7 +406,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
/// <param name="sceneObject"></param> /// <param name="sceneObject"></param>
/// <param name="assetUuids"></param> /// <param name="assetUuids"></param>
private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
{ {
AssetBase objectAsset = GetAsset(sceneObjectUuid); AssetBase objectAsset = GetAsset(sceneObjectUuid);
@ -426,7 +435,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
/// <param name="gestureUuid"></param> /// <param name="gestureUuid"></param>
/// <param name="assetUuids"></param> /// <param name="assetUuids"></param>
private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
{ {
AssetBase assetBase = GetAsset(gestureUuid); AssetBase assetBase = GetAsset(gestureUuid);
if (null == assetBase) if (null == assetBase)
@ -460,9 +469,29 @@ namespace OpenSim.Region.Framework.Scenes
// If it can be parsed as a UUID, it is an asset ID // If it can be parsed as a UUID, it is an asset ID
UUID uuid; UUID uuid;
if (UUID.TryParse(id, out uuid)) if (UUID.TryParse(id, out uuid))
assetUuids[uuid] = AssetType.Animation; assetUuids[uuid] = (sbyte)AssetType.Animation;
} }
} }
/// <summary>
/// Get the asset uuid's referenced in a material.
/// </summary>
private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
{
AssetBase assetBase = GetAsset(materialUuid);
if (null == assetBase)
return;
OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
UUID normMap = mat["NormMap"].AsUUID();
if (normMap != UUID.Zero)
assetUuids[normMap] = (sbyte)AssetType.Texture;
UUID specMap = mat["SpecMap"].AsUUID();
if (specMap != UUID.Zero)
assetUuids[specMap] = (sbyte)AssetType.Texture;
}
} }
public class HGUuidGatherer : UuidGatherer public class HGUuidGatherer : UuidGatherer

View File

@ -304,7 +304,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
private string GetImageQueuesReport(string[] showParams) private string GetImageQueuesReport(string[] showParams)
{ {
if (showParams.Length < 5 || showParams.Length > 6) if (showParams.Length < 5 || showParams.Length > 6)
return "Usage: image queues show <first-name> <last-name> [full]"; return "Usage: show image queues <first-name> <last-name> [full]";
string firstName = showParams[3]; string firstName = showParams[3];
string lastName = showParams[4]; string lastName = showParams[4];
@ -395,7 +395,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
report.AppendFormat( report.AppendFormat(
"{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
"Since", "Since",
"Pkts", "Pkts",
"Pkts", "Pkts",
@ -407,12 +407,11 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
"Q Pkts", "Q Pkts",
"Q Pkts", "Q Pkts",
"Q Pkts", "Q Pkts",
"Q Pkts",
"Q Pkts"); "Q Pkts");
report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
report.AppendFormat( report.AppendFormat(
"{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
"Last In", "Last In",
"In", "In",
"Out", "Out",
@ -424,8 +423,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
"Cloud", "Cloud",
"Task", "Task",
"Texture", "Texture",
"Asset", "Asset");
"State");
lock (m_scenes) lock (m_scenes)
{ {
@ -434,24 +432,24 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
scene.ForEachClient( scene.ForEachClient(
delegate(IClientAPI client) delegate(IClientAPI client)
{ {
bool isChild = client.SceneAgent.IsChildAgent;
if (isChild && !showChildren)
return;
string name = client.Name;
if (pname != "" && name != pname)
return;
string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
if (client is IStatsCollector) if (client is IStatsCollector)
{ {
IStatsCollector stats = (IStatsCollector)client;
bool isChild = client.SceneAgent.IsChildAgent;
if (isChild && !showChildren)
return;
string name = client.Name;
if (pname != "" && name != pname)
return;
string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
IStatsCollector stats = (IStatsCollector)client;
report.AppendLine(stats.Report()); report.AppendLine(stats.Report());
} }
}); });

View File

@ -1,657 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the 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.Security.Cryptography; // for computing md5 hash
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using Ionic.Zlib;
// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
// the available DLLs
//[assembly: Addin("MaterialsDemoModule", "1.0")]
//[assembly: AddinDependency("OpenSim", "0.5")]
namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
{
/// <summary>
///
// # # ## ##### # # # # # ####
// # # # # # # ## # # ## # # #
// # # # # # # # # # # # # # #
// # ## # ###### ##### # # # # # # # # ###
// ## ## # # # # # ## # # ## # #
// # # # # # # # # # # # ####
//
// THIS MODULE IS FOR EXPERIMENTAL USE ONLY AND MAY CAUSE REGION OR ASSET CORRUPTION!
//
////////////// WARNING //////////////////////////////////////////////////////////////////
/// This is an *Experimental* module for developing support for materials-capable viewers
/// This module should NOT be used in a production environment! It may cause data corruption and
/// viewer crashes. It should be only used to evaluate implementations of materials.
///
/// Materials are persisted via SceneObjectPart.dynattrs. This is a relatively new feature
/// of OpenSimulator and is not field proven at the time this module was written. Persistence
/// may fail or become corrupt and this could cause viewer crashes due to erroneous materials
/// data being sent to viewers. Materials descriptions might survive IAR, OAR, or other means
/// of archiving however the texture resources used by these materials probably will not as they
/// may not be adequately referenced to ensure proper archiving.
///
///
///
/// To enable this module, add this string at the bottom of OpenSim.ini:
/// [MaterialsDemoModule]
///
/// </summary>
///
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsDemoModule")]
public class MaterialsDemoModule : INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public string Name { get { return "MaterialsDemoModule"; } }
public Type ReplaceableInterface { get { return null; } }
private Scene m_scene = null;
private bool m_enabled = false;
public Dictionary<UUID, OSDMap> m_knownMaterials = new Dictionary<UUID, OSDMap>();
public void Initialise(IConfigSource source)
{
m_enabled = (source.Configs["MaterialsDemoModule"] != null);
if (!m_enabled)
return;
m_log.DebugFormat("[MaterialsDemoModule]: INITIALIZED MODULE");
}
public void Close()
{
if (!m_enabled)
return;
m_log.DebugFormat("[MaterialsDemoModule]: CLOSED MODULE");
}
public void AddRegion(Scene scene)
{
if (!m_enabled)
return;
m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
m_scene = scene;
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
// m_scene.EventManager.OnGatherUuids += GatherMaterialsUuids;
}
void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
{
foreach (var part in obj.Parts)
if (part != null)
GetStoredMaterialsForPart(part);
}
void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
{
string capsBase = "/CAPS/" + caps.CapsObjectPath;
IRequestHandler renderMaterialsPostHandler
= new RestStreamHandler("POST", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
// OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
// and POST handlers, (at least at the time this was originally written), so we first set up a POST
// handler normally and then add a GET handler via MainServer
IRequestHandler renderMaterialsGetHandler
= new RestStreamHandler("GET", capsBase + "/", RenderMaterialsGetCap, "RenderMaterials", null);
MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
// materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
IRequestHandler renderMaterialsPutHandler
= new RestStreamHandler("PUT", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
}
public void RemoveRegion(Scene scene)
{
if (!m_enabled)
return;
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
// m_scene.EventManager.OnGatherUuids -= GatherMaterialsUuids;
m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
}
public void RegionLoaded(Scene scene)
{
}
OSDMap GetMaterial(UUID id)
{
OSDMap map = null;
lock (m_knownMaterials)
{
if (m_knownMaterials.ContainsKey(id))
{
map = new OSDMap();
map["ID"] = OSD.FromBinary(id.GetBytes());
map["Material"] = m_knownMaterials[id];
}
}
return map;
}
void GetStoredMaterialsForPart(SceneObjectPart part)
{
OSD OSMaterials = null;
OSDArray matsArr = null;
if (part.DynAttrs == null)
{
m_log.Warn("[MaterialsDemoModule]: NULL DYNATTRS :( ");
}
lock (part.DynAttrs)
{
if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
{
OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
if (materialsStore == null)
return;
materialsStore.TryGetValue("Materials", out OSMaterials);
}
if (OSMaterials != null && OSMaterials is OSDArray)
matsArr = OSMaterials as OSDArray;
else
return;
}
m_log.Info("[MaterialsDemoModule]: OSMaterials: " + OSDParser.SerializeJsonString(OSMaterials));
if (matsArr == null)
{
m_log.Info("[MaterialsDemoModule]: matsArr is null :( ");
return;
}
foreach (OSD elemOsd in matsArr)
{
if (elemOsd != null && elemOsd is OSDMap)
{
OSDMap matMap = elemOsd as OSDMap;
if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
{
try
{
lock (m_knownMaterials)
m_knownMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
}
catch (Exception e)
{
m_log.Warn("[MaterialsDemoModule]: exception decoding persisted material: " + e.ToString());
}
}
}
}
}
void StoreMaterialsForPart(SceneObjectPart part)
{
try
{
if (part == null || part.Shape == null)
return;
Dictionary<UUID, OSDMap> mats = new Dictionary<UUID, OSDMap>();
Primitive.TextureEntry te = part.Shape.Textures;
if (te.DefaultTexture != null)
{
lock (m_knownMaterials)
{
if (m_knownMaterials.ContainsKey(te.DefaultTexture.MaterialID))
mats[te.DefaultTexture.MaterialID] = m_knownMaterials[te.DefaultTexture.MaterialID];
}
}
if (te.FaceTextures != null)
{
foreach (var face in te.FaceTextures)
{
if (face != null)
{
lock (m_knownMaterials)
{
if (m_knownMaterials.ContainsKey(face.MaterialID))
mats[face.MaterialID] = m_knownMaterials[face.MaterialID];
}
}
}
}
if (mats.Count == 0)
return;
OSDArray matsArr = new OSDArray();
foreach (KeyValuePair<UUID, OSDMap> kvp in mats)
{
OSDMap matOsd = new OSDMap();
matOsd["ID"] = OSD.FromUUID(kvp.Key);
matOsd["Material"] = kvp.Value;
matsArr.Add(matOsd);
}
OSDMap OSMaterials = new OSDMap();
OSMaterials["Materials"] = matsArr;
lock (part.DynAttrs)
part.DynAttrs.SetStore("OpenSim", "Materials", OSMaterials);
}
catch (Exception e)
{
m_log.Warn("[MaterialsDemoModule]: exception in StoreMaterialsForPart(): " + e.ToString());
}
}
public string RenderMaterialsPostCap(string request, string path,
string param, IOSHttpRequest httpRequest,
IOSHttpResponse httpResponse)
{
m_log.Debug("[MaterialsDemoModule]: POST cap handler");
OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
OSDMap resp = new OSDMap();
OSDMap materialsFromViewer = null;
OSDArray respArr = new OSDArray();
if (req.ContainsKey("Zipped"))
{
OSD osd = null;
byte[] inBytes = req["Zipped"].AsBinary();
try
{
osd = ZDecompressBytesToOsd(inBytes);
if (osd != null)
{
if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
{
foreach (OSD elem in (OSDArray)osd)
{
try
{
UUID id = new UUID(elem.AsBinary(), 0);
lock (m_knownMaterials)
{
if (m_knownMaterials.ContainsKey(id))
{
m_log.Info("[MaterialsDemoModule]: request for known material ID: " + id.ToString());
OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(id.GetBytes());
matMap["Material"] = m_knownMaterials[id];
respArr.Add(matMap);
}
else
m_log.Info("[MaterialsDemoModule]: request for UNKNOWN material ID: " + id.ToString());
}
}
catch (Exception e)
{
// report something here?
continue;
}
}
}
else if (osd is OSDMap) // reqest to assign a material
{
materialsFromViewer = osd as OSDMap;
if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
{
OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
if (matsOsd is OSDArray)
{
OSDArray matsArr = matsOsd as OSDArray;
try
{
foreach (OSDMap matsMap in matsArr)
{
m_log.Debug("[MaterialsDemoModule]: processing matsMap: " + OSDParser.SerializeJsonString(matsMap));
uint matLocalID = 0;
try { matLocalID = matsMap["ID"].AsUInteger(); }
catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"ID\" from matsMap: " + e.Message); }
m_log.Debug("[MaterialsDemoModule]: matLocalId: " + matLocalID.ToString());
OSDMap mat = null;
try { mat = matsMap["Material"] as OSDMap; }
catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"Material\" from matsMap: " + e.Message); }
m_log.Debug("[MaterialsDemoModule]: mat: " + OSDParser.SerializeJsonString(mat));
UUID id = HashOsd(mat);
lock (m_knownMaterials)
m_knownMaterials[id] = mat;
var sop = m_scene.GetSceneObjectPart(matLocalID);
if (sop == null)
m_log.Debug("[MaterialsDemoModule]: null SOP for localId: " + matLocalID.ToString());
else
{
var te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
if (te == null)
{
m_log.Debug("[MaterialsDemoModule]: null TextureEntry for localId: " + matLocalID.ToString());
}
else
{
int face = -1;
if (matsMap.ContainsKey("Face"))
{
face = matsMap["Face"].AsInteger();
if (te.FaceTextures == null) // && face == 0)
{
if (te.DefaultTexture == null)
m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture is null");
else
te.DefaultTexture.MaterialID = id;
}
else
{
if (te.FaceTextures.Length >= face - 1)
{
if (te.FaceTextures[face] == null)
te.DefaultTexture.MaterialID = id;
else
te.FaceTextures[face].MaterialID = id;
}
}
}
else
{
if (te.DefaultTexture != null)
te.DefaultTexture.MaterialID = id;
}
m_log.Debug("[MaterialsDemoModule]: setting material ID for face " + face.ToString() + " to " + id.ToString());
//we cant use sop.UpdateTextureEntry(te); because it filters so do it manually
if (sop.ParentGroup != null)
{
sop.Shape.TextureEntry = te.GetBytes();
sop.TriggerScriptChangedEvent(Changed.TEXTURE);
sop.UpdateFlag = UpdateRequired.FULL;
sop.ParentGroup.HasGroupChanged = true;
sop.ScheduleFullUpdate();
StoreMaterialsForPart(sop);
}
}
}
}
}
catch (Exception e)
{
m_log.Warn("[MaterialsDemoModule]: exception processing received material: " + e.Message);
}
}
}
}
}
}
catch (Exception e)
{
m_log.Warn("[MaterialsDemoModule]: exception decoding zipped CAP payload: " + e.Message);
//return "";
}
m_log.Debug("[MaterialsDemoModule]: knownMaterials.Count: " + m_knownMaterials.Count.ToString());
}
resp["Zipped"] = ZCompressOSD(respArr, false);
string response = OSDParser.SerializeLLSDXmlString(resp);
//m_log.Debug("[MaterialsDemoModule]: cap request: " + request);
m_log.Debug("[MaterialsDemoModule]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
m_log.Debug("[MaterialsDemoModule]: cap response: " + response);
return response;
}
public string RenderMaterialsGetCap(string request, string path,
string param, IOSHttpRequest httpRequest,
IOSHttpResponse httpResponse)
{
m_log.Debug("[MaterialsDemoModule]: GET cap handler");
OSDMap resp = new OSDMap();
int matsCount = 0;
OSDArray allOsd = new OSDArray();
lock (m_knownMaterials)
{
foreach (KeyValuePair<UUID, OSDMap> kvp in m_knownMaterials)
{
OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
matMap["Material"] = kvp.Value;
allOsd.Add(matMap);
matsCount++;
}
}
resp["Zipped"] = ZCompressOSD(allOsd, false);
m_log.Debug("[MaterialsDemoModule]: matsCount: " + matsCount.ToString());
return OSDParser.SerializeLLSDXmlString(resp);
}
static string ZippedOsdBytesToString(byte[] bytes)
{
try
{
return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
}
catch (Exception e)
{
return "ZippedOsdBytesToString caught an exception: " + e.ToString();
}
}
/// <summary>
/// computes a UUID by hashing a OSD object
/// </summary>
/// <param name="osd"></param>
/// <returns></returns>
private static UUID HashOsd(OSD osd)
{
using (var md5 = MD5.Create())
using (MemoryStream ms = new MemoryStream(OSDParser.SerializeLLSDBinary(osd, false)))
return new UUID(md5.ComputeHash(ms), 0);
}
public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
{
OSD osd = null;
using (MemoryStream msSinkCompressed = new MemoryStream())
{
using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
{
CopyStream(new MemoryStream(OSDParser.SerializeLLSDBinary(inOsd, useHeader)), zOut);
zOut.Close();
}
msSinkCompressed.Seek(0L, SeekOrigin.Begin);
osd = OSD.FromBinary( msSinkCompressed.ToArray());
}
return osd;
}
public static OSD ZDecompressBytesToOsd(byte[] input)
{
OSD osd = null;
using (MemoryStream msSinkUnCompressed = new MemoryStream())
{
using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
{
CopyStream(new MemoryStream(input), zOut);
zOut.Close();
}
msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
}
return osd;
}
static void CopyStream(System.IO.Stream input, System.IO.Stream output)
{
byte[] buffer = new byte[2048];
int len;
while ((len = input.Read(buffer, 0, 2048)) > 0)
{
output.Write(buffer, 0, len);
}
output.Flush();
}
// FIXME: This code is currently still in UuidGatherer since we cannot use Scene.EventManager as some
// calls to the gatherer are done for objects with no scene.
// /// <summary>
// /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
// /// </summary>
// /// <param name="part"></param>
// /// <param name="assetUuids"></param>
// private void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
// {
// // scan thru the dynAttrs map of this part for any textures used as materials
// OSD osdMaterials = null;
//
// lock (part.DynAttrs)
// {
// if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
// {
// OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
// if (materialsStore == null)
// return;
//
// materialsStore.TryGetValue("Materials", out osdMaterials);
// }
//
// if (osdMaterials != null)
// {
// //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
//
// if (osdMaterials is OSDArray)
// {
// OSDArray matsArr = osdMaterials as OSDArray;
// foreach (OSDMap matMap in matsArr)
// {
// try
// {
// if (matMap.ContainsKey("Material"))
// {
// OSDMap mat = matMap["Material"] as OSDMap;
// if (mat.ContainsKey("NormMap"))
// {
// UUID normalMapId = mat["NormMap"].AsUUID();
// if (normalMapId != UUID.Zero)
// {
// assetUuids[normalMapId] = AssetType.Texture;
// //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
// }
// }
// if (mat.ContainsKey("SpecMap"))
// {
// UUID specularMapId = mat["SpecMap"].AsUUID();
// if (specularMapId != UUID.Zero)
// {
// assetUuids[specularMapId] = AssetType.Texture;
// //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
// }
// }
// }
//
// }
// catch (Exception e)
// {
// m_log.Warn("[MaterialsDemoModule]: exception getting materials: " + e.Message);
// }
// }
// }
// }
// }
// }
}
}

View File

@ -0,0 +1,590 @@
/*
* 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.Security.Cryptography; // for computing md5 hash
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
using Ionic.Zlib;
// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
// the available DLLs
//[assembly: Addin("MaterialsModule", "1.0")]
//[assembly: AddinDependency("OpenSim", "0.5")]
namespace OpenSim.Region.OptionalModules.Materials
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
public class MaterialsModule : INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public string Name { get { return "MaterialsModule"; } }
public Type ReplaceableInterface { get { return null; } }
private Scene m_scene = null;
private bool m_enabled = false;
public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
public void Initialise(IConfigSource source)
{
IConfig config = source.Configs["Materials"];
if (config == null)
return;
m_enabled = config.GetBoolean("enable_materials", true);
if (!m_enabled)
return;
m_log.DebugFormat("[Materials]: Initialized");
}
public void Close()
{
if (!m_enabled)
return;
}
public void AddRegion(Scene scene)
{
if (!m_enabled)
return;
m_scene = scene;
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
}
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
{
foreach (var part in obj.Parts)
if (part != null)
GetStoredMaterialsInPart(part);
}
private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
{
string capsBase = "/CAPS/" + caps.CapsObjectPath;
IRequestHandler renderMaterialsPostHandler
= new RestStreamHandler("POST", capsBase + "/",
(request, path, param, httpRequest, httpResponse)
=> RenderMaterialsPostCap(request, agentID),
"RenderMaterials", null);
caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
// OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
// and POST handlers, (at least at the time this was originally written), so we first set up a POST
// handler normally and then add a GET handler via MainServer
IRequestHandler renderMaterialsGetHandler
= new RestStreamHandler("GET", capsBase + "/",
(request, path, param, httpRequest, httpResponse)
=> RenderMaterialsGetCap(request),
"RenderMaterials", null);
MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
// materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
IRequestHandler renderMaterialsPutHandler
= new RestStreamHandler("PUT", capsBase + "/",
(request, path, param, httpRequest, httpResponse)
=> RenderMaterialsPostCap(request, agentID),
"RenderMaterials", null);
MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
}
public void RemoveRegion(Scene scene)
{
if (!m_enabled)
return;
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
}
public void RegionLoaded(Scene scene)
{
}
/// <summary>
/// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'.
/// </summary>
/// <param name="part"></param>
private void GetLegacyStoredMaterialsInPart(SceneObjectPart part)
{
if (part.DynAttrs == null)
return;
OSD OSMaterials = null;
OSDArray matsArr = null;
lock (part.DynAttrs)
{
if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
{
OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
if (materialsStore == null)
return;
materialsStore.TryGetValue("Materials", out OSMaterials);
}
if (OSMaterials != null && OSMaterials is OSDArray)
matsArr = OSMaterials as OSDArray;
else
return;
}
if (matsArr == null)
return;
foreach (OSD elemOsd in matsArr)
{
if (elemOsd != null && elemOsd is OSDMap)
{
OSDMap matMap = elemOsd as OSDMap;
if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
{
try
{
lock (m_regionMaterials)
m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
}
catch (Exception e)
{
m_log.Warn("[Materials]: exception decoding persisted legacy material: " + e.ToString());
}
}
}
}
}
/// <summary>
/// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
/// </summary>
private void GetStoredMaterialsInPart(SceneObjectPart part)
{
if (part.Shape == null)
return;
var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
if (te == null)
return;
GetLegacyStoredMaterialsInPart(part);
GetStoredMaterialInFace(part, te.DefaultTexture);
foreach (Primitive.TextureEntryFace face in te.FaceTextures)
{
if (face != null)
GetStoredMaterialInFace(part, face);
}
}
/// <summary>
/// Find the materials used in one Face, and add them to 'm_regionMaterials'.
/// </summary>
private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
{
UUID id = face.MaterialID;
if (id == UUID.Zero)
return;
lock (m_regionMaterials)
{
if (m_regionMaterials.ContainsKey(id))
return;
byte[] data = m_scene.AssetService.GetData(id.ToString());
if (data == null)
{
m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
return;
}
OSDMap mat;
try
{
mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
}
catch (Exception e)
{
m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
return;
}
m_regionMaterials[id] = mat;
}
}
public string RenderMaterialsPostCap(string request, UUID agentID)
{
OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
OSDMap resp = new OSDMap();
OSDMap materialsFromViewer = null;
OSDArray respArr = new OSDArray();
if (req.ContainsKey("Zipped"))
{
OSD osd = null;
byte[] inBytes = req["Zipped"].AsBinary();
try
{
osd = ZDecompressBytesToOsd(inBytes);
if (osd != null)
{
if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
{
foreach (OSD elem in (OSDArray)osd)
{
try
{
UUID id = new UUID(elem.AsBinary(), 0);
lock (m_regionMaterials)
{
if (m_regionMaterials.ContainsKey(id))
{
OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(id.GetBytes());
matMap["Material"] = m_regionMaterials[id];
respArr.Add(matMap);
}
else
{
m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
// Theoretically we could try to load the material from the assets service,
// but that shouldn't be necessary because the viewer should only request
// materials that exist in a prim on the region, and all of these materials
// are already stored in m_regionMaterials.
}
}
}
catch (Exception e)
{
m_log.Error("Error getting materials in response to viewer request", e);
continue;
}
}
}
else if (osd is OSDMap) // request to assign a material
{
materialsFromViewer = osd as OSDMap;
if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
{
OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
if (matsOsd is OSDArray)
{
OSDArray matsArr = matsOsd as OSDArray;
try
{
foreach (OSDMap matsMap in matsArr)
{
uint primLocalID = 0;
try {
primLocalID = matsMap["ID"].AsUInteger();
}
catch (Exception e) {
m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
continue;
}
OSDMap mat = null;
try
{
mat = matsMap["Material"] as OSDMap;
}
catch (Exception e)
{
m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
continue;
}
SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
if (sop == null)
{
m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
continue;
}
if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID))
{
m_log.WarnFormat("User {0} can't edit object {1} {2}", agentID, sop.Name, sop.UUID);
continue;
}
Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
if (te == null)
{
m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
continue;
}
UUID id;
if (mat == null)
{
// This happens then the user removes a material from a prim
id = UUID.Zero;
}
else
{
id = StoreMaterialAsAsset(agentID, mat, sop);
}
int face = -1;
if (matsMap.ContainsKey("Face"))
{
face = matsMap["Face"].AsInteger();
Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
faceEntry.MaterialID = id;
}
else
{
if (te.DefaultTexture == null)
m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
else
te.DefaultTexture.MaterialID = id;
}
//m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
sop.Shape.TextureEntry = te.GetBytes();
if (sop.ParentGroup != null)
{
sop.TriggerScriptChangedEvent(Changed.TEXTURE);
sop.UpdateFlag = UpdateRequired.FULL;
sop.ParentGroup.HasGroupChanged = true;
sop.ScheduleFullUpdate();
}
}
}
catch (Exception e)
{
m_log.Warn("[Materials]: exception processing received material ", e);
}
}
}
}
}
}
catch (Exception e)
{
m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
//return "";
}
}
resp["Zipped"] = ZCompressOSD(respArr, false);
string response = OSDParser.SerializeLLSDXmlString(resp);
//m_log.Debug("[Materials]: cap request: " + request);
//m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
//m_log.Debug("[Materials]: cap response: " + response);
return response;
}
private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
{
UUID id;
// Material UUID = hash of the material's data.
// This makes materials deduplicate across the entire grid (but isn't otherwise required).
byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
using (var md5 = MD5.Create())
id = new UUID(md5.ComputeHash(data), 0);
lock (m_regionMaterials)
{
if (!m_regionMaterials.ContainsKey(id))
{
m_regionMaterials[id] = mat;
// This asset might exist already, but it's ok to try to store it again
string name = "Material " + ChooseMaterialName(mat, sop);
name = name.Substring(0, Math.Min(64, name.Length)).Trim();
AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
asset.Data = data;
m_scene.AssetService.Store(asset);
}
}
return id;
}
/// <summary>
/// Use heuristics to choose a good name for the material.
/// </summary>
private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
{
UUID normMap = mat["NormMap"].AsUUID();
if (normMap != UUID.Zero)
{
AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
return asset.Name;
}
UUID specMap = mat["SpecMap"].AsUUID();
if (specMap != UUID.Zero)
{
AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
return asset.Name;
}
if (sop.Name != "Primitive")
return sop.Name;
if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
return sop.ParentGroup.Name;
return "";
}
public string RenderMaterialsGetCap(string request)
{
OSDMap resp = new OSDMap();
int matsCount = 0;
OSDArray allOsd = new OSDArray();
lock (m_regionMaterials)
{
foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
{
OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
matMap["Material"] = kvp.Value;
allOsd.Add(matMap);
matsCount++;
}
}
resp["Zipped"] = ZCompressOSD(allOsd, false);
return OSDParser.SerializeLLSDXmlString(resp);
}
private static string ZippedOsdBytesToString(byte[] bytes)
{
try
{
return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
}
catch (Exception e)
{
return "ZippedOsdBytesToString caught an exception: " + e.ToString();
}
}
/// <summary>
/// computes a UUID by hashing a OSD object
/// </summary>
/// <param name="osd"></param>
/// <returns></returns>
private static UUID HashOsd(OSD osd)
{
byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
using (var md5 = MD5.Create())
return new UUID(md5.ComputeHash(data), 0);
}
public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
{
OSD osd = null;
byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
using (MemoryStream msSinkCompressed = new MemoryStream())
{
using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
{
zOut.Write(data, 0, data.Length);
}
msSinkCompressed.Seek(0L, SeekOrigin.Begin);
osd = OSD.FromBinary(msSinkCompressed.ToArray());
}
return osd;
}
public static OSD ZDecompressBytesToOsd(byte[] input)
{
OSD osd = null;
using (MemoryStream msSinkUnCompressed = new MemoryStream())
{
using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
{
zOut.Write(input, 0, input.Length);
}
msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
}
return osd;
}
}
}

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) Contributors
* 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 Mono.Addins;
using System;
using System.Reflection;
using System.Threading;
using System.Text;
using System.Net;
using System.Net.Sockets;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreCommandsModule")]
public class JsonStoreCommandsModule : INonSharedRegionModule
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IConfig m_config = null;
private bool m_enabled = false;
private Scene m_scene = null;
//private IJsonStoreModule m_store;
private JsonStoreModule m_store;
#region Region Module interface
// -----------------------------------------------------------------
/// <summary>
/// Name of this shared module is it's class name
/// </summary>
// -----------------------------------------------------------------
public string Name
{
get { return this.GetType().Name; }
}
// -----------------------------------------------------------------
/// <summary>
/// Initialise this shared module
/// </summary>
/// <param name="scene">this region is getting initialised</param>
/// <param name="source">nini config, we are not using this</param>
// -----------------------------------------------------------------
public void Initialise(IConfigSource config)
{
try
{
if ((m_config = config.Configs["JsonStore"]) == null)
{
// There is no configuration, the module is disabled
// m_log.InfoFormat("[JsonStore] no configuration info");
return;
}
m_enabled = m_config.GetBoolean("Enabled", m_enabled);
}
catch (Exception e)
{
m_log.Error("[JsonStore]: initialization error: {0}", e);
return;
}
if (m_enabled)
m_log.DebugFormat("[JsonStore]: module is enabled");
}
// -----------------------------------------------------------------
/// <summary>
/// everything is loaded, perform post load configuration
/// </summary>
// -----------------------------------------------------------------
public void PostInitialise()
{
}
// -----------------------------------------------------------------
/// <summary>
/// Nothing to do on close
/// </summary>
// -----------------------------------------------------------------
public void Close()
{
}
// -----------------------------------------------------------------
/// <summary>
/// </summary>
// -----------------------------------------------------------------
public void AddRegion(Scene scene)
{
if (m_enabled)
{
m_scene = scene;
}
}
// -----------------------------------------------------------------
/// <summary>
/// </summary>
// -----------------------------------------------------------------
public void RemoveRegion(Scene scene)
{
// need to remove all references to the scene in the subscription
// list to enable full garbage collection of the scene object
}
// -----------------------------------------------------------------
/// <summary>
/// Called when all modules have been added for a region. This is
/// where we hook up events
/// </summary>
// -----------------------------------------------------------------
public void RegionLoaded(Scene scene)
{
if (m_enabled)
{
m_scene = scene;
m_store = (JsonStoreModule) m_scene.RequestModuleInterface<IJsonStoreModule>();
if (m_store == null)
{
m_log.ErrorFormat("[JsonStoreCommands]: JsonModule interface not defined");
m_enabled = false;
return;
}
scene.AddCommand("JsonStore", this, "jsonstore stats", "jsonstore stats",
"Display statistics about the state of the JsonStore module", "",
CmdStats);
}
}
/// -----------------------------------------------------------------
/// <summary>
/// </summary>
// -----------------------------------------------------------------
public Type ReplaceableInterface
{
get { return null; }
}
#endregion
#region Commands
private void CmdStats(string module, string[] cmd)
{
if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
return;
JsonStoreStats stats = m_store.GetStoreStats();
MainConsole.Instance.OutputFormat("{0}\t{1}",m_scene.RegionInfo.RegionName,stats.StoreCount);
}
#endregion
}
}

View File

@ -42,7 +42,6 @@ using OpenSim.Region.Framework.Scenes;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace OpenSim.Region.OptionalModules.Scripting.JsonStore namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
{ {
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
@ -60,6 +59,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
private Scene m_scene = null; private Scene m_scene = null;
private Dictionary<UUID,JsonStore> m_JsonValueStore; private Dictionary<UUID,JsonStore> m_JsonValueStore;
private UUID m_sharedStore; private UUID m_sharedStore;
#region Region Module interface #region Region Module interface
@ -140,6 +140,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
m_sharedStore = UUID.Zero; m_sharedStore = UUID.Zero;
m_JsonValueStore = new Dictionary<UUID,JsonStore>(); m_JsonValueStore = new Dictionary<UUID,JsonStore>();
m_JsonValueStore.Add(m_sharedStore,new JsonStore("")); m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
} }
} }
@ -149,6 +151,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
// ----------------------------------------------------------------- // -----------------------------------------------------------------
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
{ {
scene.EventManager.OnObjectBeingRemovedFromScene -= EventManagerOnObjectBeingRemovedFromScene;
// need to remove all references to the scene in the subscription // need to remove all references to the scene in the subscription
// list to enable full garbage collection of the scene object // list to enable full garbage collection of the scene object
} }
@ -161,7 +165,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
// ----------------------------------------------------------------- // -----------------------------------------------------------------
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
{ {
if (m_enabled) {} if (m_enabled)
{
}
} }
/// ----------------------------------------------------------------- /// -----------------------------------------------------------------
@ -175,8 +181,39 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
#endregion #endregion
#region SceneEvents
// -----------------------------------------------------------------
/// <summary>
///
/// </summary>
// -----------------------------------------------------------------
public void EventManagerOnObjectBeingRemovedFromScene(SceneObjectGroup obj)
{
obj.ForEachPart(delegate(SceneObjectPart sop) { DestroyStore(sop.UUID); } );
}
#endregion
#region ScriptInvocationInteface #region ScriptInvocationInteface
// -----------------------------------------------------------------
/// <summary>
///
/// </summary>
// -----------------------------------------------------------------
public JsonStoreStats GetStoreStats()
{
JsonStoreStats stats;
lock (m_JsonValueStore)
{
stats.StoreCount = m_JsonValueStore.Count;
}
return stats;
}
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/// <summary> /// <summary>
/// ///

View File

@ -59,7 +59,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
private IScriptModuleComms m_comms; private IScriptModuleComms m_comms;
private IJsonStoreModule m_store; private IJsonStoreModule m_store;
private Dictionary<UUID,HashSet<UUID>> m_scriptStores = new Dictionary<UUID,HashSet<UUID>>();
#region Region Module interface #region Region Module interface
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@ -126,6 +128,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
// ----------------------------------------------------------------- // -----------------------------------------------------------------
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
{ {
scene.EventManager.OnScriptReset += HandleScriptReset;
scene.EventManager.OnRemoveScript += HandleScriptReset;
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@ -134,10 +138,32 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
// ----------------------------------------------------------------- // -----------------------------------------------------------------
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
{ {
scene.EventManager.OnScriptReset -= HandleScriptReset;
scene.EventManager.OnRemoveScript -= HandleScriptReset;
// need to remove all references to the scene in the subscription // need to remove all references to the scene in the subscription
// list to enable full garbage collection of the scene object // list to enable full garbage collection of the scene object
} }
// -----------------------------------------------------------------
/// <summary>
/// </summary>
// -----------------------------------------------------------------
private void HandleScriptReset(uint localID, UUID itemID)
{
HashSet<UUID> stores;
lock (m_scriptStores)
{
if (! m_scriptStores.TryGetValue(itemID, out stores))
return;
m_scriptStores.Remove(itemID);
}
foreach (UUID id in stores)
m_store.DestroyStore(id);
}
// ----------------------------------------------------------------- // -----------------------------------------------------------------
/// <summary> /// <summary>
/// Called when all modules have been added for a region. This is /// Called when all modules have been added for a region. This is
@ -250,6 +276,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
if (! m_store.CreateStore(value, ref uuid)) if (! m_store.CreateStore(value, ref uuid))
GenerateRuntimeError("Failed to create Json store"); GenerateRuntimeError("Failed to create Json store");
lock (m_scriptStores)
{
if (! m_scriptStores.ContainsKey(scriptID))
m_scriptStores[scriptID] = new HashSet<UUID>();
m_scriptStores[scriptID].Add(uuid);
}
return uuid; return uuid;
} }
@ -261,6 +294,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
[ScriptInvocation] [ScriptInvocation]
public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
{ {
lock(m_scriptStores)
{
if (m_scriptStores.ContainsKey(scriptID))
m_scriptStores[scriptID].Remove(storeID);
}
return m_store.DestroyStore(storeID) ? 1 : 0; return m_store.DestroyStore(storeID) ? 1 : 0;
} }

View File

@ -434,6 +434,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
return wl; return wl;
} }
/// <summary> /// <summary>
/// Set the current Windlight scene /// Set the current Windlight scene
/// </summary> /// </summary>
@ -446,13 +447,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSShoutError("LightShare functions are not enabled."); LSShoutError("LightShare functions are not enabled.");
return 0; return 0;
} }
if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
{ {
LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
return 0;
if (sp == null || sp.GodLevel < 200)
{
LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
return 0;
}
} }
int success = 0; int success = 0;
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (LightShareModule.EnableWindlight) if (LightShareModule.EnableWindlight)
{ {
RegionLightShareData wl = getWindlightProfileFromRules(rules); RegionLightShareData wl = getWindlightProfileFromRules(rules);
@ -465,8 +474,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSShoutError("Windlight module is disabled"); LSShoutError("Windlight module is disabled");
return 0; return 0;
} }
return success; return success;
} }
public void lsClearWindlightScene() public void lsClearWindlightScene()
{ {
if (!m_LSFunctionsEnabled) if (!m_LSFunctionsEnabled)
@ -474,17 +485,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSShoutError("LightShare functions are not enabled."); LSShoutError("LightShare functions are not enabled.");
return; return;
} }
if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
{ {
LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
return;
if (sp == null || sp.GodLevel < 200)
{
LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
return;
}
} }
m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false; m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false;
if (m_host.ParentGroup.Scene.SimulationDataService != null) if (m_host.ParentGroup.Scene.SimulationDataService != null)
m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID); m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID);
m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile(); m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile();
} }
/// <summary> /// <summary>
/// Set the current Windlight scene to a target avatar /// Set the current Windlight scene to a target avatar
/// </summary> /// </summary>
@ -497,13 +516,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSShoutError("LightShare functions are not enabled."); LSShoutError("LightShare functions are not enabled.");
return 0; return 0;
} }
if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200)
if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
{ {
LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
return 0;
if (sp == null || sp.GodLevel < 200)
{
LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners.");
return 0;
}
} }
int success = 0; int success = 0;
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (LightShareModule.EnableWindlight) if (LightShareModule.EnableWindlight)
{ {
RegionLightShareData wl = getWindlightProfileFromRules(rules); RegionLightShareData wl = getWindlightProfileFromRules(rules);
@ -515,8 +542,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSShoutError("Windlight module is disabled"); LSShoutError("Windlight module is disabled");
return 0; return 0;
} }
return success; return success;
} }
} }
} }

View File

@ -3005,6 +3005,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return ret; return ret;
} }
public LSL_Vector osGetRegionSize()
{
CheckThreatLevel(ThreatLevel.None, "osGetRegionSize");
m_host.AddScriptLPS(1);
bool isMegaregion;
IRegionCombinerModule rcMod = World.RequestModuleInterface<IRegionCombinerModule>();
if (rcMod != null)
isMegaregion = rcMod.IsRootForMegaregion(World.RegionInfo.RegionID);
else
isMegaregion = false;
if (isMegaregion)
{
Vector2 size = rcMod.GetSizeOfMegaregion(World.RegionInfo.RegionID);
return new LSL_Vector(size.X, size.Y, Constants.RegionHeight);
}
else
{
return new LSL_Vector((float)Constants.RegionSize, (float)Constants.RegionSize, Constants.RegionHeight);
}
}
public int osGetSimulatorMemory() public int osGetSimulatorMemory()
{ {
CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory"); CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory");

View File

@ -336,6 +336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
key osGetMapTexture(); key osGetMapTexture();
key osGetRegionMapTexture(string regionName); key osGetRegionMapTexture(string regionName);
LSL_List osGetRegionStats(); LSL_List osGetRegionStats();
vector osGetRegionSize();
int osGetSimulatorMemory(); int osGetSimulatorMemory();
void osKickAvatar(string FirstName,string SurName,string alert); void osKickAvatar(string FirstName,string SurName,string alert);

View File

@ -858,6 +858,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osGetRegionStats(); return m_OSSL_Functions.osGetRegionStats();
} }
public vector osGetRegionSize()
{
return m_OSSL_Functions.osGetRegionSize();
}
/// <summary> /// <summary>
/// Returns the amount of memory in use by the Simulator Daemon. /// Returns the amount of memory in use by the Simulator Daemon.
/// Amount in bytes - if >= 4GB, returns 4GB. (LSL is not 64-bit aware) /// Amount in bytes - if >= 4GB, returns 4GB. (LSL is not 64-bit aware)

View File

@ -35,7 +35,14 @@ namespace OpenSim.Services.Interfaces
public interface IOfflineIMService public interface IOfflineIMService
{ {
List<GridInstantMessage> GetMessages(UUID principalID); List<GridInstantMessage> GetMessages(UUID principalID);
bool StoreMessage(GridInstantMessage im, out string reason); bool StoreMessage(GridInstantMessage im, out string reason);
/// <summary>
/// Delete messages to or from this user (or group).
/// </summary>
/// <param name="userID">A user or group ID</param>
void DeleteMessages(UUID userID);
} }
public class OfflineIMDataUtils public class OfflineIMDataUtils

View File

@ -799,11 +799,6 @@ namespace OpenSim.Tests.Common.Mock
{ {
OnRegionHandShakeReply(this); OnRegionHandShakeReply(this);
} }
if (OnCompleteMovementToRegion != null)
{
OnCompleteMovementToRegion(this, true);
}
} }
public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)

View File

@ -117,8 +117,6 @@ namespace OpenSim.Tests.Common
/// Parse a UUID stem into a full UUID. /// Parse a UUID stem into a full UUID.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Yes, this is completely inconsistent with ParseTail but this is probably a better way to do it,
/// UUIDs are conceptually not hexadecmial numbers.
/// The fragment will come at the start of the UUID. The rest will be 0s /// The fragment will come at the start of the UUID. The rest will be 0s
/// </remarks> /// </remarks>
/// <returns></returns> /// <returns></returns>
@ -143,5 +141,24 @@ namespace OpenSim.Tests.Common
{ {
return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail)); return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail));
} }
/// <summary>
/// Parse a UUID tail section into a full UUID.
/// </summary>
/// <remarks>
/// The fragment will come at the end of the UUID. The rest will be 0s
/// </remarks>
/// <returns></returns>
/// <param name='frag'>
/// A UUID fragment that will be parsed into a full UUID. Therefore, it can only contain
/// cahracters which are valid in a UUID, except for "-" which is currently only allowed if a full UUID is
/// given as the 'fragment'.
/// </param>
public static UUID ParseTail(string stem)
{
string rawUuid = stem.PadLeft(32, '0');
return UUID.Parse(rawUuid);
}
} }
} }

View File

@ -4,123 +4,6 @@
<name>OpenMetaverse.StructuredData</name> <name>OpenMetaverse.StructuredData</name>
</assembly> </assembly>
<members> <members>
<member name="T:OpenMetaverse.StructuredData.OSDType">
<summary>
</summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Unknown">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Boolean">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Integer">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Real">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.String">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.UUID">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Date">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.URI">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Binary">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Map">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Array">
<summary></summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDException">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSD">
<summary>
</summary>
</member>
<member name="M:OpenMetaverse.StructuredData.OSD.SerializeMembers(System.Object)">
<summary>
Uses reflection to create an SDMap from all of the SD
serializable types in an object
</summary>
<param name="obj">Class or struct containing serializable types</param>
<returns>An SDMap holding the serialized values from the
container object</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSD.DeserializeMembers(System.Object@,OpenMetaverse.StructuredData.OSDMap)">
<summary>
Uses reflection to deserialize member variables in an object from
an SDMap
</summary>
<param name="obj">Reference to an object to fill with deserialized
values</param>
<param name="serialized">Serialized values to put in the target
object</param>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDBoolean">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDInteger">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDReal">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDString">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDUUID">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDDate">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDUri">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDBinary">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDMap">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDArray">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDParser"> <member name="T:OpenMetaverse.StructuredData.OSDParser">
<summary> <summary>
@ -345,5 +228,122 @@
<param name="c"></param> <param name="c"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:OpenMetaverse.StructuredData.OSDType">
<summary>
</summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Unknown">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Boolean">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Integer">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Real">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.String">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.UUID">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Date">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.URI">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Binary">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Map">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Array">
<summary></summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDException">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSD">
<summary>
</summary>
</member>
<member name="M:OpenMetaverse.StructuredData.OSD.SerializeMembers(System.Object)">
<summary>
Uses reflection to create an SDMap from all of the SD
serializable types in an object
</summary>
<param name="obj">Class or struct containing serializable types</param>
<returns>An SDMap holding the serialized values from the
container object</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSD.DeserializeMembers(System.Object@,OpenMetaverse.StructuredData.OSDMap)">
<summary>
Uses reflection to deserialize member variables in an object from
an SDMap
</summary>
<param name="obj">Reference to an object to fill with deserialized
values</param>
<param name="serialized">Serialized values to put in the target
object</param>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDBoolean">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDInteger">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDReal">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDString">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDUUID">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDDate">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDUri">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDBinary">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDMap">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDArray">
<summary>
</summary>
</member>
</members> </members>
</doc> </doc>

Binary file not shown.

View File

@ -687,6 +687,12 @@
; enable_windlight = false ; enable_windlight = false
[Materials]
;# {enable_materials} {} {Enable Materials support?} {true false} true
;; This enables the use of Materials.
; enable_materials = true
[DataSnapshot] [DataSnapshot]
;# {index_sims} {} {Enable data snapshotting (search)?} {true false} false ;# {index_sims} {} {Enable data snapshotting (search)?} {true false} false
;; The following set of configs pertains to search. ;; The following set of configs pertains to search.

View File

@ -539,6 +539,16 @@
; ;
;TextureSendLimit = 20 ;TextureSendLimit = 20
; CannibalizeTextureRate allows bandwidth to be moved from the
; UDP texture throttle to the task throttle. Since most viewers
; use HTTP textures, this provides a means of using what is largely
; unused bandwidth in the total throttle. The value is the proportion
; of the texture rate to move to the task queue. It must be between
; 0.0 (none of the bandwidth is cannibalized) and 0.9 (90% of the
; bandwidth is grabbed)
;
; CannibalizeTextureRate = 0.5
; Quash and remove any light properties from attachments not on the ; Quash and remove any light properties from attachments not on the
; hands. This allows flashlights and lanterns to function, but kills ; hands. This allows flashlights and lanterns to function, but kills
; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps ; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps