diff --git a/.gitignore b/.gitignore
index dc4087e488..fae7509131 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,7 @@ Examples/*.dll
OpenSim.build
OpenSim.sln
OpenSim.suo
+OpenSim.userprefs
Prebuild/Prebuild.build
Prebuild/Prebuild.sln
TestResult.xml
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 9dd0797411..7c07a2ab38 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -92,6 +92,7 @@ what it is today.
* Flyte Xevious
* Garmin Kawaguichi
* Gryc Ueusp
+* Hiro Lecker
* Imaze Rhiano
* Intimidated
* Jeremy Bongio (IBM)
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index f040ff78e0..8d25e180ca 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -163,7 +163,7 @@ namespace OpenSim.Capabilities.Handlers
if (texture == null)
{
- //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
+// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// Fetch locally or remotely. Misses return a 404
texture = m_assetService.Get(textureID.ToString());
@@ -197,7 +197,7 @@ namespace OpenSim.Capabilities.Handlers
}
else // it was on the cache
{
- //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
+// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
@@ -219,14 +219,30 @@ namespace OpenSim.Capabilities.Handlers
int start, end;
if (TryParseRange(range, out start, out end))
{
-
// Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status
if (start >= texture.Data.Length)
{
+// m_log.DebugFormat(
+// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
+// texture.ID, start, texture.Data.Length);
+
+ // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
+ // Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
+ // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
+ // received a very small texture may attempt to fetch bytes from the server past the
+ // range of data that it received originally. Whether this happens appears to depend on whether
+ // the viewer's estimation of how large a request it needs to make for certain discard levels
+ // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
+ // level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
+ // here will cause the viewer to treat the texture as bad and never display the full resolution
+ // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
+
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
- // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
- response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
+// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
+// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
+ response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
+ response.ContentType = texture.Metadata.ContentType;
}
else
{
@@ -234,12 +250,18 @@ namespace OpenSim.Capabilities.Handlers
start = Utils.Clamp(start, 0, end);
int len = end - start + 1;
- //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
+// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
// Always return PartialContent, even if the range covered the entire data length
// We were accidentally sending back 404 before in this situation
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
+ //
+ // We also do not want to send back OK even if the whole range was satisfiable since this causes
+ // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
+// if (end > maxEnd)
+// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
+// else
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentLength = len;
@@ -368,4 +390,4 @@ namespace OpenSim.Capabilities.Handlers
return null;
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index 016a1744ef..bb094ed6f5 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
{
public class VersionInfo
{
- private const string VERSION_NUMBER = "0.7.4CM";
+ private const string VERSION_NUMBER = "0.7.5CM";
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
public enum Flavour
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 7d7176fc07..d698239545 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -49,12 +49,8 @@ using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
-[assembly: Addin("FlotsamAssetCache", "1.1")]
-[assembly: AddinDependency("OpenSim", "0.5")]
-
-namespace Flotsam.RegionModules.AssetCache
+namespace OpenSim.Region.CoreModules.Asset
{
- [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
{
private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index c91b25fac2..9276d1a526 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -35,7 +35,7 @@ using Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenMetaverse.Assets;
-using Flotsam.RegionModules.AssetCache;
+using OpenSim.Region.CoreModules.Asset;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
index 424e0ab384..a09945e2a7 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -34,6 +34,7 @@
+
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
new file mode 100644
index 0000000000..fce9490da6
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
@@ -0,0 +1,61 @@
+/*
+ * 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.Drawing;
+using OpenSim.Region.Framework.Interfaces;
+
+namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
+{
+ public class DynamicTexture : IDynamicTexture
+ {
+ public string InputCommands { get; private set; }
+ public Uri InputUri { get; private set; }
+ public string InputParams { get; private set; }
+ public byte[] Data { get; private set; }
+ public Size Size { get; private set; }
+ public bool IsReuseable { get; private set; }
+
+ public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
+ {
+ InputCommands = inputCommands;
+ InputParams = inputParams;
+ Data = data;
+ Size = size;
+ IsReuseable = isReuseable;
+ }
+
+ public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
+ {
+ InputUri = inputUri;
+ InputParams = inputParams;
+ Data = data;
+ Size = size;
+ IsReuseable = isReuseable;
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 3eedf498c4..1f340df1b1 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
{
- //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const int ALL_SIDES = -1;
@@ -54,6 +54,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
///
public bool ReuseTextures { get; set; }
+ ///
+ /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
+ ///
+ ///
+ /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
+ /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
+ /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
+ /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
+ /// to work around this problem.
+ public bool ReuseLowDataTextures { get; set; }
+
private Dictionary RegisteredScenes = new Dictionary();
private Dictionary RenderPlugins =
@@ -83,18 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
///
/// Called by code which actually renders the dynamic texture to supply texture data.
///
- ///
- ///
- /// True if the data generated can be reused for subsequent identical requests
- public void ReturnData(UUID id, byte[] data, bool isReuseable)
+ ///
+ ///
+ public void ReturnData(UUID updaterId, IDynamicTexture texture)
{
DynamicTextureUpdater updater = null;
lock (Updaters)
{
- if (Updaters.ContainsKey(id))
+ if (Updaters.ContainsKey(updaterId))
{
- updater = Updaters[id];
+ updater = Updaters[updaterId];
}
}
@@ -103,11 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (RegisteredScenes.ContainsKey(updater.SimUUID))
{
Scene scene = RegisteredScenes[updater.SimUUID];
- UUID newTextureID = updater.DataReceived(data, scene);
+ UUID newTextureID = updater.DataReceived(texture.Data, scene);
- if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
+ if (ReuseTextures
+ && !updater.BlendWithOldTexture
+ && texture.IsReuseable
+ && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
+ {
m_reuseableDynamicTextures.Store(
- GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
+ GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
+ }
}
}
@@ -123,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
}
+ ///
+ /// Determines whether the texture is reuseable based on its data size.
+ ///
+ ///
+ /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
+ /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
+ /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
+ ///
+ ///
+ private bool IsDataSizeReuseable(IDynamicTexture texture)
+ {
+// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
+ int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
+
+// m_log.DebugFormat(
+// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
+// discardLevel2DataThreshold, texture.Data.Length);
+
+ return discardLevel2DataThreshold < texture.Data.Length;
+ }
+
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
string extraParams, int updateTimer)
{
@@ -249,10 +285,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
}
+// m_log.DebugFormat(
+// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
+// part.Name, part.ParentGroup.Scene.Name);
+
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
}
else
{
+// m_log.DebugFormat(
+// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
+// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
+
// No need to add to updaters as the texture is always the same. Not that this functionality
// apppears to be implemented anyway.
updater.UpdatePart(part, (UUID)objReusableTextureUUID);
@@ -285,7 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
IConfig texturesConfig = config.Configs["Textures"];
if (texturesConfig != null)
+ {
ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
+ ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
+ }
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{
@@ -448,8 +495,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface();
if (cacheLayerDecode != null)
{
- cacheLayerDecode.Decode(asset.FullID, asset.Data);
- cacheLayerDecode = null;
+ if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
+ m_log.WarnFormat(
+ "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
+ asset.ID, part.Name, part.ParentGroup.Scene.Name);
}
UUID oldID = UpdatePart(part, asset.FullID);
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 2b3a0f29ff..45e652788a 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,6 +32,7 @@ using System.Net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Imaging;
+using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
@@ -73,12 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
// return false;
// }
- public byte[] ConvertUrl(string url, string extraParams)
+ public IDynamicTexture ConvertUrl(string url, string extraParams)
{
return null;
}
- public byte[] ConvertData(string bodyData, string extraParams)
+ public IDynamicTexture ConvertData(string bodyData, string extraParams)
{
return null;
}
@@ -171,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
private void HttpRequestReturn(IAsyncResult result)
{
-
RequestState state = (RequestState) result.AsyncState;
WebRequest request = (WebRequest) state.Request;
Stream stream = null;
byte[] imageJ2000 = new byte[0];
+ Size newSize = new Size(0, 0);
try
{
@@ -188,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
try
{
Bitmap image = new Bitmap(stream);
- Size newsize;
// TODO: make this a bit less hard coded
if ((image.Height < 64) && (image.Width < 64))
{
- newsize = new Size(32, 32);
+ newSize.Width = 32;
+ newSize.Height = 32;
}
else if ((image.Height < 128) && (image.Width < 128))
{
- newsize = new Size(64, 64);
+ newSize.Width = 64;
+ newSize.Height = 64;
}
else if ((image.Height < 256) && (image.Width < 256))
{
- newsize = new Size(128, 128);
+ newSize.Width = 128;
+ newSize.Height = 128;
}
else if ((image.Height < 512 && image.Width < 512))
{
- newsize = new Size(256, 256);
+ newSize.Width = 256;
+ newSize.Height = 256;
}
else if ((image.Height < 1024 && image.Width < 1024))
{
- newsize = new Size(512, 512);
+ newSize.Width = 512;
+ newSize.Height = 512;
}
else
{
- newsize = new Size(1024, 1024);
+ newSize.Width = 1024;
+ newSize.Height = 1024;
}
- Bitmap resize = new Bitmap(image, newsize);
-
- imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
+ using (Bitmap resize = new Bitmap(image, newSize))
+ {
+ imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
+ }
}
catch (Exception)
{
@@ -233,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
}
catch (WebException)
{
-
}
finally
{
@@ -243,10 +249,13 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
}
}
- m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
+ m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
imageJ2000.Length, state.RequestID);
- m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
+ m_textureManager.ReturnData(
+ state.RequestID,
+ new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
+ request.RequestUri, null, imageJ2000, newSize, false));
}
#region Nested type: RequestState
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index b50c0bd7cd..41bacccf9e 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
m_dtm = new DynamicTextureModule();
m_dtm.ReuseTextures = reuseTextures;
+// m_dtm.ReuseLowDataTextures = reuseTextures;
m_vrm = new VectorRenderModule();
@@ -201,6 +202,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
public void TestRepeatSameDrawReusingTexture()
{
TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
@@ -228,6 +230,46 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
+ ///
+ /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
+ /// problems for current viewers.
+ ///
+ ///
+ /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
+ /// texture
+ ///
+ [Test]
+ public void TestRepeatSameDrawLowDataTexture()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "1024",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "1024",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
[Test]
public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
{
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index f687646e76..1e17b02b33 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -35,6 +35,7 @@ using System.Net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Imaging;
+using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
@@ -46,6 +47,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
public class VectorRenderModule : IRegionModule, IDynamicTextureRender
{
+ // These fields exist for testing purposes, please do not remove.
+// private static bool s_flipper;
+// private static byte[] s_asset1Data;
+// private static byte[] s_asset2Data;
+
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
@@ -80,20 +86,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
// return lines.Any((str, r) => str.StartsWith("Image"));
// }
- public byte[] ConvertUrl(string url, string extraParams)
+ public IDynamicTexture ConvertUrl(string url, string extraParams)
{
return null;
}
- public byte[] ConvertData(string bodyData, string extraParams)
+ public IDynamicTexture ConvertData(string bodyData, string extraParams)
{
- bool reuseable;
- return Draw(bodyData, extraParams, out reuseable);
- }
-
- private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
- {
- return Draw(bodyData, extraParams, out reuseable);
+ return Draw(bodyData, extraParams);
}
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -104,10 +104,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
{
// XXX: This isn't actually being done asynchronously!
- bool reuseable;
- byte[] data = ConvertData(bodyData, extraParams, out reuseable);
-
- m_textureManager.ReturnData(id, data, reuseable);
+ m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
return true;
}
@@ -161,6 +158,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
m_textureManager.RegisterRender(GetContentType(), this);
}
+
+ // This code exists for testing purposes, please do not remove.
+// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
+// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
+
+ // Terrain dirt - smallest bin/assets file (6004 bytes)
+// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
}
public void Close()
@@ -179,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
#endregion
- private byte[] Draw(string data, string extraParams, out bool reuseable)
+ private IDynamicTexture Draw(string data, string extraParams)
{
// We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -322,6 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
Bitmap bitmap = null;
Graphics graph = null;
+ bool reuseable = false;
try
{
@@ -364,6 +369,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
byte[] imageJ2000 = new byte[0];
+
+ // This code exists for testing purposes, please do not remove.
+// if (s_flipper)
+// imageJ2000 = s_asset1Data;
+// else
+// imageJ2000 = s_asset2Data;
+//
+// s_flipper = !s_flipper;
try
{
@@ -376,7 +389,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
e.Message, e.StackTrace);
}
- return imageJ2000;
+ return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
+ data, extraParams, imageJ2000, new Size(width, height), reuseable);
}
finally
{
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index b286d172e4..57ae5497ee 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common;
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
{
[TestFixture]
- public class GridConnectorsTests
+ public class GridConnectorsTests : OpenSimTestCase
{
LocalGridServicesConnector m_LocalConnector;
private void SetUp()
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 5deaf5264b..904110e457 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -51,7 +51,7 @@ using RegionSettings = OpenSim.Framework.RegionSettings;
namespace OpenSim.Region.CoreModules.World.Archiver.Tests
{
[TestFixture]
- public class ArchiverTests
+ public class ArchiverTests : OpenSimTestCase
{
private Guid m_lastRequestId;
private string m_lastErrorMessage;
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 3c48d07bb6..33f6c3fbe0 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -222,6 +222,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
}
+ // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
+ // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
+ // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
+ // this map tile simply takes a lot of memory.
+ GC.Collect();
+ m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
+
return bitmap;
}
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 1a3bcbbc71..6df5cc2ac5 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -25,6 +25,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using System;
+using System.Drawing;
using System.IO;
using OpenMetaverse;
@@ -33,7 +35,14 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IDynamicTextureManager
{
void RegisterRender(string handleType, IDynamicTextureRender render);
- void ReturnData(UUID id, byte[] data, bool isReuseable);
+
+ ///
+ /// Used by IDynamicTextureRender implementations to return renders
+ ///
+ ///
+ ///
+ ///
+ void ReturnData(UUID id, IDynamicTexture texture);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
int updateTimer);
@@ -125,11 +134,53 @@ namespace OpenSim.Region.Framework.Interfaces
// ///
// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
- byte[] ConvertUrl(string url, string extraParams);
- byte[] ConvertData(string bodyData, string extraParams);
+ IDynamicTexture ConvertUrl(string url, string extraParams);
+ IDynamicTexture ConvertData(string bodyData, string extraParams);
+
bool AsyncConvertUrl(UUID id, string url, string extraParams);
bool AsyncConvertData(UUID id, string bodyData, string extraParams);
+
void GetDrawStringSize(string text, string fontName, int fontSize,
out double xSize, out double ySize);
}
+
+ public interface IDynamicTexture
+ {
+ ///
+ /// Input commands used to generate this data.
+ ///
+ ///
+ /// Null if input commands were not used.
+ ///
+ string InputCommands { get; }
+
+ ///
+ /// Uri used to generate this data.
+ ///
+ ///
+ /// Null if a uri was not used.
+ ///
+ Uri InputUri { get; }
+
+ ///
+ /// Extra input params used to generate this data.
+ ///
+ string InputParams { get; }
+
+ ///
+ /// Texture data.
+ ///
+ byte[] Data { get; }
+
+ ///
+ /// Size of texture.
+ ///
+ Size Size { get; }
+
+ ///
+ /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same
+ /// texture).
+ ///
+ bool IsReuseable { get; }
+ }
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 8fb6c3b8fa..d94d5ef247 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -4810,6 +4810,18 @@ namespace OpenSim.Region.Framework.Scenes
return m_sceneGraph.GetSceneObjectGroup(name);
}
+ ///
+ /// Attempt to get the SOG via its UUID
+ ///
+ ///
+ ///
+ ///
+ public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
+ {
+ sog = GetSceneObjectGroup(fullID);
+ return sog != null;
+ }
+
///
/// Get a prim by name from the scene (will return the first
/// found, if there are more than one prim with the same name)
@@ -4841,6 +4853,18 @@ namespace OpenSim.Region.Framework.Scenes
return m_sceneGraph.GetSceneObjectPart(fullID);
}
+ ///
+ /// Attempt to get a prim via its UUID
+ ///
+ ///
+ ///
+ ///
+ public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
+ {
+ sop = GetSceneObjectPart(fullID);
+ return sop != null;
+ }
+
///
/// Get a scene object group that contains the prim with the given local id
///
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3e8c7e52b7..0176921795 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3631,13 +3631,16 @@ namespace OpenSim.Region.Framework.Scenes
public List GetAttachments(uint attachmentPoint)
{
List attachments = new List();
-
- lock (m_attachments)
+
+ if (attachmentPoint >= 0)
{
- foreach (SceneObjectGroup so in m_attachments)
+ lock (m_attachments)
{
- if (attachmentPoint == so.AttachmentPoint)
- attachments.Add(so);
+ foreach (SceneObjectGroup so in m_attachments)
+ {
+ if (attachmentPoint == so.AttachmentPoint)
+ attachments.Add(so);
+ }
}
}
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 3144d76432..190fca0253 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -39,11 +39,8 @@ using OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
using Mono.Addins;
-[assembly: Addin("RegionCombinerModule", "0.1")]
-[assembly: AddinDependency("OpenSim", "0.5")]
namespace OpenSim.Region.RegionCombinerModule
{
- [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
new file mode 100644
index 0000000000..13cb8b6dc5
--- /dev/null
+++ b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 84cf6cab65..cde2d9f068 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// ---------- Integer ----------
else if (lslparm is LSL_Integer)
{
- if (type == typeof(int))
+ if (type == typeof(int) || type == typeof(float))
return (int)(LSL_Integer)lslparm;
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7aacfd4b0f..a44ced497b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1682,6 +1682,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
+ MessageObject(objUUID, message);
+ }
+
+ private void MessageObject(UUID objUUID, string message)
+ {
object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
@@ -3272,6 +3277,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
+ #region Attachment commands
+
public void osForceAttachToAvatar(int attachmentPoint)
{
CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
@@ -3361,6 +3368,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
((LSL_Api)m_LSL_Api).DetachFromAvatar();
}
+ public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
+ {
+ CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
+
+ m_host.AddScriptLPS(1);
+
+ UUID targetUUID;
+ ScenePresence target;
+ LSL_List resp = new LSL_List();
+
+ if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
+ {
+ foreach (object point in attachmentPoints.Data)
+ {
+ LSL_Integer ipoint = new LSL_Integer(
+ (point is LSL_Integer || point is int || point is uint) ?
+ (int)point :
+ 0
+ );
+ resp.Add(ipoint);
+ if (ipoint == 0)
+ {
+ // indicates zero attachments
+ resp.Add(new LSL_Integer(0));
+ }
+ else
+ {
+ // gets the number of attachments on the attachment point
+ resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
+ }
+ }
+ }
+
+ return resp;
+ }
+
+ public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
+ {
+ CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
+ m_host.AddScriptLPS(1);
+
+ UUID targetUUID;
+ ScenePresence target;
+
+ if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
+ {
+ List aps = new List();
+ foreach (object point in attachmentPoints.Data)
+ {
+ int ipoint;
+ if (int.TryParse(point.ToString(), out ipoint))
+ {
+ aps.Add(ipoint);
+ }
+ }
+
+ List attachments = new List();
+
+ bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
+ bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
+
+ if (msgAll && invertPoints)
+ {
+ return;
+ }
+ else if (msgAll || invertPoints)
+ {
+ attachments = target.GetAttachments();
+ }
+ else
+ {
+ foreach (int point in aps)
+ {
+ if (point > 0)
+ {
+ attachments.AddRange(target.GetAttachments((uint)point));
+ }
+ }
+ }
+
+ // if we have no attachments at this point, exit now
+ if (attachments.Count == 0)
+ {
+ return;
+ }
+
+ List ignoreThese = new List();
+
+ if (invertPoints)
+ {
+ foreach (SceneObjectGroup attachment in attachments)
+ {
+ if (aps.Contains((int)attachment.AttachmentPoint))
+ {
+ ignoreThese.Add(attachment);
+ }
+ }
+ }
+
+ foreach (SceneObjectGroup attachment in ignoreThese)
+ {
+ attachments.Remove(attachment);
+ }
+ ignoreThese.Clear();
+
+ // if inverting removed all attachments to check, exit now
+ if (attachments.Count < 1)
+ {
+ return;
+ }
+
+ if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
+ {
+ foreach (SceneObjectGroup attachment in attachments)
+ {
+ if (attachment.RootPart.CreatorID != m_host.CreatorID)
+ {
+ ignoreThese.Add(attachment);
+ }
+ }
+
+ foreach (SceneObjectGroup attachment in ignoreThese)
+ {
+ attachments.Remove(attachment);
+ }
+ ignoreThese.Clear();
+
+ // if filtering by same object creator removed all
+ // attachments to check, exit now
+ if (attachments.Count == 0)
+ {
+ return;
+ }
+ }
+
+ if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
+ {
+ foreach (SceneObjectGroup attachment in attachments)
+ {
+ if (attachment.RootPart.CreatorID != m_item.CreatorID)
+ {
+ ignoreThese.Add(attachment);
+ }
+ }
+
+ foreach (SceneObjectGroup attachment in ignoreThese)
+ {
+ attachments.Remove(attachment);
+ }
+ ignoreThese.Clear();
+
+ // if filtering by object creator must match originating
+ // script creator removed all attachments to check,
+ // exit now
+ if (attachments.Count == 0)
+ {
+ return;
+ }
+ }
+
+ foreach (SceneObjectGroup attachment in attachments)
+ {
+ MessageObject(attachment.RootPart.UUID, message);
+ }
+ }
+ }
+
+ #endregion
+
///
/// Checks if thing is a UUID.
///
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 07149b65e8..0ea363a448 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
void osAvatarPlayAnimation(string avatar, string animation);
void osAvatarStopAnimation(string avatar, string animation);
- // Attachment commands
+ #region Attachment commands
///
/// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
@@ -192,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
/// Nothing happens if the object is not attached.
void osForceDetachFromAvatar();
+ ///
+ /// Returns a strided list of the specified attachment points and the number of attachments on those points.
+ ///
+ /// avatar UUID
+ /// list of ATTACH_* constants
+ ///
+ LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
+
+ ///
+ /// Sends a specified message to the specified avatar's attachments on
+ /// the specified attachment points.
+ ///
+ ///
+ /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
+ ///
+ /// avatar UUID
+ /// message string
+ /// list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.
+ /// flags further constraining the attachments to deliver the message to.
+ void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
+
+ #endregion
+
//texture draw functions
string osMovePen(string drawList, int x, int y);
string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 05ba222b9d..c78840765f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int ATTACH_HUD_BOTTOM = 37;
public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
+ #region osMessageAttachments constants
+
+ ///
+ /// Instructs osMessageAttachements to send the message to attachments
+ /// on every point.
+ ///
+ ///
+ /// One might expect this to be named OS_ATTACH_ALL, but then one might
+ /// also expect functions designed to attach or detach or get
+ /// attachments to work with it too. Attaching a no-copy item to
+ /// many attachments could be dangerous.
+ /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
+ /// message from being sent.
+ /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
+ /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
+ /// sent- this is expected behaviour.
+ ///
+ public const int OS_ATTACH_MSG_ALL = -65535;
+
+ ///
+ /// Instructs osMessageAttachements to invert how the attachment points
+ /// list should be treated (e.g. go from inclusive operation to
+ /// exclusive operation).
+ ///
+ ///
+ /// This might be used if you want to deliver a message to one set of
+ /// attachments and a different message to everything else. With
+ /// this flag, you only need to build one explicit list for both calls.
+ ///
+ public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
+
+ ///
+ /// Instructs osMessageAttachments to only send the message to
+ /// attachments with a CreatorID that matches the host object CreatorID
+ ///
+ ///
+ /// This would be used if distributed in an object vendor/updater server.
+ ///
+ public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
+
+ ///
+ /// Instructs osMessageAttachments to only send the message to
+ /// attachments with a CreatorID that matches the sending script CreatorID
+ ///
+ ///
+ /// This might be used if the script is distributed independently of a
+ /// containing object.
+ ///
+ public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
+
+ #endregion
+
public const int LAND_LEVEL = 0;
public const int LAND_RAISE = 1;
public const int LAND_LOWER = 2;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index ba1ade2285..52ca3da154 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
}
- // Avatar functions
+ #region Attachment commands
public void osForceAttachToAvatar(int attachmentPoint)
{
@@ -311,6 +311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_OSSL_Functions.osForceDetachFromAvatar();
}
+ public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
+ {
+ return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
+ }
+
+ public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
+ {
+ m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
+ }
+
+ #endregion
+
// Texture Draw functions
public string osMovePen(string drawList, int x, int y)
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index b137c05889..0cff6ed5df 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
@@ -71,10 +72,17 @@ namespace OpenSim.Server.Base
//
private string m_pidFile = String.Empty;
+ ///
+ /// Time at which this server was started
+ ///
+ protected DateTime m_startuptime;
+
// Handle all the automagical stuff
//
public ServicesServerBase(string prompt, string[] args)
{
+ m_startuptime = DateTime.Now;
+
// Save raw arguments
//
m_Arguments = args;
@@ -250,6 +258,10 @@ namespace OpenSim.Server.Base
"command-script