| Anonymous | Login | Signup for a new account | 2013-05-25 21:32 UTC | ![]() |
| Main | My View | View Issues | Change Log | Roadmap | Summary | My Account |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | |||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | |||||
| 0006126 | opensim | [REGION] Script Functions | public | 2012-08-03 14:07 | 2012-08-03 16:14 | |||||
| Reporter | SignpostMarv | |||||||||
| Assigned To | ||||||||||
| Priority | normal | Severity | feature | Reproducibility | N/A | |||||
| Status | patch included | Resolution | open | |||||||
| Platform | OS | OS Version | ||||||||
| Product Version | ||||||||||
| Target Version | Fixed in Version | |||||||||
| Summary | 0006126: axis-aligned bounds-constrained chat | |||||||||
| Description | Feature request for allowing scripts to chat to one or more variably-sized & absolutely-positioned bounding boxes & spheres (as opposed to the current choice of pre-defined whisper/say/shout effective spheres + region-wide). | |||||||||
| Tags | No tags attached. | |||||||||
| Git Revision or version number | 630b3e7dca | |||||||||
| Run Mode | Standalone (1 Region) | |||||||||
| Physics Engine | BasicPhysics | |||||||||
| Environment | .NET / Windows32 | |||||||||
| Mono Version | None | |||||||||
| Viewer | ||||||||||
| Attached Files | From fb45726aeda9c8530a1ef368053ea1f95657f1be Mon Sep 17 00:00:00 2001
From: SignpostMarv <github@signpostmarv.name>
Date: Fri, 3 Aug 2012 14:34:51 +0100
Subject: [PATCH 1/2] Added getters so one can check the currently configured
chat distances from outside the class
---
OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | 6 ++++++
OpenSim/Region/Framework/Interfaces/IWorldComm.cs | 4 ++++
2 files changed, 10 insertions(+)
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index 8358bc0..5357dc6 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -94,9 +94,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
private Queue m_pending;
private Queue m_pendingQ;
private Scene m_scene;
+
private int m_whisperdistance = 10;
+ public int WhisperDistance { get { return m_whisperdistance; } }
+
private int m_saydistance = 20;
+ public int SayDistance { get { return m_saydistance; } }
+
private int m_shoutdistance = 100;
+ public int ShoutDistance { get { return m_shoutdistance; } }
#region IRegionModule Members
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index 4e74781..4d41a20 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -49,6 +49,10 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IWorldComm
{
+ int WhisperDistance { get; }
+ int SayDistance { get; }
+ int ShoutDistance { get; }
+
/// <summary>
/// Total number of listeners
/// </summary>
--
1.7.11.msysgit.1
From 122aeb4814498f6b516dc718a91eb1a66f0cc9a9 Mon Sep 17 00:00:00 2001
From: SignpostMarv <github@signpostmarv.name>
Date: Fri, 3 Aug 2012 14:37:29 +0100
Subject: [PATCH 2/2] implementing an extensible osChat() function through
which one can apply multiple rules about which
listeners should receieve the message, such as
inclusive & exclusive bounding boxes & spheres.
---
OpenSim/Framework/Bounds.cs | 112 ++++++++++++++++++
.../Scripting/WorldComm/WorldCommModule.cs | 65 +++++++++++
OpenSim/Region/Framework/Interfaces/IWorldComm.cs | 12 ++
.../Shared/Api/Implementation/OSSL_Api.cs | 128 +++++++++++++++++++++
.../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 8 ++
.../Shared/Api/Runtime/LSL_Constants.cs | 20 ++++
.../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 5 +
7 files changed, 350 insertions(+)
create mode 100644 OpenSim/Framework/Bounds.cs
diff --git a/OpenSim/Framework/Bounds.cs b/OpenSim/Framework/Bounds.cs
new file mode 100644
index 0000000..5dd11c9
--- /dev/null
+++ b/OpenSim/Framework/Bounds.cs
@@ -0,0 +1,112 @@
+/*
+ * 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 OpenMetaverse;
+
+namespace OpenSim.Framework
+{
+ public enum BoundsType
+ {
+ Sphere = 0,
+ Box = 1
+ }
+
+ public interface IBounds
+ {
+ BoundsType BoundingType { get; }
+
+ Vector3 Center { get; set; }
+
+ bool Contains(Vector3 point);
+ }
+
+ public class BoundingBox : IBounds
+ {
+ public BoundsType BoundingType { get { return BoundsType.Box; } }
+
+ public Vector3 Center { get; set; }
+ public Vector3 Size { get; set; }
+
+ public Vector3 Min
+ {
+ get { return Center - (Size / 2.0f); }
+ }
+
+ public Vector3 Max
+ {
+ get { return Center + (Size / 2.0f); }
+ }
+
+ public BoundingBox(Vector3 center, Vector3 size)
+ {
+ Center = center;
+ Size = size;
+ }
+
+ public bool Contains(Vector3 point)
+ {
+ Vector3 min = Min;
+ Vector3 max = Max;
+ return (
+ point.X >= Min.X && point.Y >= Min.Y && point.Z >= Min.Z &&
+ point.X <= Max.X && point.Y <= Max.Y && point.Z <= Max.Z
+ );
+ }
+
+ /*
+ public bool Contains(Vector3 point, Quaternion translate)
+ {
+ Vector3 relative = (point - Center) / translate;
+
+ return (
+ relative.X >= 0 && relative.Y >= 0 && relative.Z >= 0 &&
+ relative.X <= Size.X && relative.Y <= Size.Y && relative.Z <= Size.Z
+ );
+ }
+ */
+ }
+
+ public class BoundingSphere : IBounds
+ {
+ public BoundsType BoundingType { get { return BoundsType.Sphere; } }
+
+ public Vector3 Center { get; set; }
+ public float Radius { get; set; }
+
+ public BoundingSphere(Vector3 center, float radius)
+ {
+ Center = center;
+ Radius = radius;
+ }
+
+ public bool Contains(Vector3 point)
+ {
+ return Vector3.Distance(Center, point) <= Math.Abs(Radius);
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index 5357dc6..1991828 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -296,6 +296,71 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
}
}
+ public void DeliverMessage(int channel, string name, UUID id, string msg, List<IBounds> include, List<IBounds> exclude)
+ {
+ // If there are no inclusive bounds, then the message will not reach anyone.
+ if (include.Count < 1)
+ {
+ return;
+ }
+
+ // If somehow the prim left the scene before we get to here, act as if this method was not called.
+ if (m_scene.GetSceneObjectPart(id) == null)
+ {
+ return;
+ }
+
+ // rather than queuing messages as soon as we've found something, we're compiling a list and *then* queuing messages.
+ List<ListenerInfo> deliverables = new List<ListenerInfo>();
+
+ // First we need to get listeners that match the message
+ foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
+ {
+ // Dont process if this message is from yourself!
+ if (li.GetHostID().Equals(id))
+ continue;
+
+ SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID());
+
+ // listening object is no longer in scene, so we want to skip it
+ if (sPart == null)
+ {
+ continue;
+ }
+
+ bool includeThisOne = false;
+ foreach (IBounds bounds in include)
+ {
+ if (bounds.Contains(sPart.AbsolutePosition))
+ {
+ includeThisOne = true;
+ break;
+ }
+ }
+ if (!includeThisOne)
+ {
+ continue;
+ }
+ foreach (IBounds bounds in exclude)
+ {
+ if (bounds.Contains(sPart.AbsolutePosition))
+ {
+ includeThisOne = false;
+ break;
+ }
+ }
+ if (includeThisOne)
+ {
+ deliverables.Add(li);
+ }
+ }
+
+ foreach (ListenerInfo li in deliverables)
+ {
+ QueueMessage(new ListenerInfo(li, name, id, msg));
+ }
+ }
+
/// <summary>
/// Delivers the message to a scene entity.
/// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index 4d41a20..b25cd43 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
@@ -90,6 +91,17 @@ namespace OpenSim.Region.Framework.Interfaces
void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg);
/// <summary>
+ /// Attempt to deliver a message
+ /// </summary>
+ /// <param name="channel">channel to sent on</param>
+ /// <param name="name">name of sender (object or avatar)</param>
+ /// <param name="id">key of sender (object or avatar)</param>
+ /// <param name="msg">msg to sent</param>
+ /// <param name="include">Only listeners inside these bounds will receieve the message</param>
+ /// <param name="exclude">Listeners that are inside include but also inside exclude constraints will not receieve the message.</param>
+ void DeliverMessage(int channel, string name, UUID id, string msg, List<IBounds> include, List<IBounds> exclude);
+
+ /// <summary>
/// Delivers the message to a specified object in the region.
/// </summary>
/// <param name='target'>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index bcd1a6f..2425ef0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3322,5 +3322,133 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
}
+
+ public void osChat(int channel, string message, LSL_List rules)
+ {
+ if (rules.Length < 1)
+ {
+ m_LSL_Api.llSay(channel, message);
+ return;
+ }
+
+ CheckThreatLevel(ThreatLevel.Moderate, "osChat");
+ m_host.AddScriptLPS(1);
+
+ IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
+ if (wComm == null)
+ {
+ return;
+ }
+
+ List<IBounds> constrain = new List<IBounds>();
+ List<IBounds> exclude = new List<IBounds>();
+ bool ignoreFurtherBounds = false;
+
+ int idx = 0;
+ while (idx < rules.Length)
+ {
+ int code = rules.GetLSLIntegerItem(idx++);
+ int remain = rules.Length - idx;
+
+ #region rules parser
+
+ switch (code)
+ {
+ case ScriptBaseClass.OS_CHAT_TYPE:
+ if (remain < 1)
+ {
+ return;
+ }
+ int newChatType = rules.GetLSLIntegerItem(idx++);
+ // If a specific chat type is specified, we're going to ignore the previous bounds.
+ switch (newChatType)
+ {
+ case ScriptBaseClass.OS_CHAT_TYPE_WHISPER:
+ constrain = new List<IBounds>{
+ new BoundingSphere(Vector3.Zero, wComm.WhisperDistance)
+ };
+ break;
+ case ScriptBaseClass.OS_CHAT_TYPE_SHOUT:
+ constrain = new List<IBounds>{
+ new BoundingSphere(Vector3.Zero, wComm.ShoutDistance)
+ };
+ break;
+ default:
+ constrain = new List<IBounds>{
+ new BoundingSphere(Vector3.Zero, wComm.SayDistance)
+ };
+ break;
+ }
+ ignoreFurtherBounds = true;
+ break;
+ case ScriptBaseClass.OS_CHAT_CONSTRAINT_BOUNDS:
+ case ScriptBaseClass.OS_CHAT_EXCLUDE_BOUNDS:
+ bool constrainBounds = code == ScriptBaseClass.OS_CHAT_CONSTRAINT_BOUNDS;
+ if (remain < 1)
+ {
+ return;
+ }
+ int boundsType = rules.GetLSLIntegerItem(idx++);
+ if (remain < 2 && boundsType != ScriptBaseClass.OS_CHAT_BOUNDING_BOX_REGION)
+ {
+ return;
+ }
+ IBounds newBounds = null;
+ // region box needs no further parameters.
+ Vector3 center = Vector3.Zero;
+ if (boundsType != ScriptBaseClass.OS_CHAT_BOUNDING_BOX_REGION)
+ {
+ LSL_Vector lslCenter = rules.GetVector3Item(idx++);
+ center = new Vector3((float)lslCenter.x, (float)lslCenter.y, (float)lslCenter.z);
+ }
+ switch (boundsType)
+ {
+ case ScriptBaseClass.OS_CHAT_BOUNDING_SPHERE_WHISPER:
+ newBounds = new BoundingSphere(center, wComm.WhisperDistance);
+ break;
+ case ScriptBaseClass.OS_CHAT_BOUNDING_SPHERE_SAY:
+ newBounds = new BoundingSphere(center, wComm.SayDistance);
+ break;
+ case ScriptBaseClass.OS_CHAT_BOUNDING_SPHERE_SHOUT:
+ newBounds = new BoundingSphere(center, wComm.ShoutDistance);
+ break;
+ case ScriptBaseClass.OS_CHAT_BOUNDING_BOX_REGION:
+ newBounds = new BoundingBox(new Vector3(Constants.RegionSize / 2, Constants.RegionSize / 2, Constants.RegionSize * 8), new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize * 16));
+ break;
+ case ScriptBaseClass.OS_CHAT_BOUNDING_SPHERE:
+ if (remain < 3)
+ {
+ return;
+ }
+ newBounds = new BoundingSphere(center, (float)rules.GetLSLFloatItem(idx++));
+ break;
+ case ScriptBaseClass.OS_CHAT_BOUNDING_BOX:
+ if (remain < 3)
+ {
+ return;
+ }
+ LSL_Vector boxSize = rules.GetVector3Item(idx++);
+ newBounds = new BoundingBox(center, new Vector3((float)boxSize.x, (float)boxSize.y, (float)boxSize.z));
+ break;
+ }
+ if (!ignoreFurtherBounds && newBounds != null)
+ {
+ if (constrainBounds)
+ {
+ constrain.Add(newBounds);
+ }
+ else
+ {
+ exclude.Add(newBounds);
+ }
+ }
+ break;
+ }
+
+ #endregion
+ }
+
+ wComm.DeliverMessage(channel, m_host.Name, m_host.UUID, message, constrain, exclude);
+ }
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 1f000a3..f2a01e0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -305,5 +305,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
/// </summary>
/// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
LSL_Key osGetRezzingObject();
+
+ /// <summary>
+ /// Make a chat message with specified rules affecting the recipients.
+ /// </summary>
+ /// <param name="channel"></param>
+ /// <param name="message"></param>
+ /// <param name="rules"></param>
+ void osChat(int channel, string message, LSL_List rules);
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index c3eada0..89cc4d5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -660,5 +660,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public static readonly LSLInteger RCERR_UNKNOWN = -1;
public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3;
+
+ #region constants for osChat
+
+ public const int OS_CHAT_TYPE = 0;
+ public const int OS_CHAT_CONSTRAINT_BOUNDS = 1;
+ public const int OS_CHAT_EXCLUDE_BOUNDS = 2;
+
+ public const int OS_CHAT_TYPE_WHISPER = 0;
+ public const int OS_CHAT_TYPE_SAY = 1;
+ public const int OS_CHAT_TYPE_SHOUT = 2;
+
+ public const int OS_CHAT_BOUNDING_SPHERE = 0;
+ public const int OS_CHAT_BOUNDING_SPHERE_WHISPER = 1;
+ public const int OS_CHAT_BOUNDING_SPHERE_SAY = 2;
+ public const int OS_CHAT_BOUNDING_SPHERE_SHOUT = 3;
+ public const int OS_CHAT_BOUNDING_BOX = 4;
+ public const int OS_CHAT_BOUNDING_BOX_REGION = 5;
+
+ #endregion
+
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 94405d2..e83e1a0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -950,5 +950,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
return m_OSSL_Functions.osGetRezzingObject();
}
+
+ public void osChat(integer channel, string message, LSL_List rules)
+ {
+ m_OSSL_Functions.osChat(channel, message, rules);
+ }
}
}
--
1.7.11.msysgit.1
| |||||||||
Notes |
|
|
(0021974) SignpostMarv (reporter) 2012-08-03 14:12 |
patch for feature limited to receipt by objects only uploaded, along with test OAR. |
|
(0021975) SignpostMarv (reporter) 2012-08-03 14:17 |
I'm unsure as to where exactly to implement this for receipt by avatars :s DeliverChatToAvatars looks like the right place, but it'd also look like I'd have to modify OSChatMessage to support the inclusive & exclusive List<IBounds> properties. |
|
(0021976) SignpostMarv (reporter) 2012-08-03 16:14 |
Added a class that centralises the include/exclude calculation so it can be used in other tasks (such as delivering messages to avatars). |
Issue History |
|||
| Date Modified | Username | Field | Change |
| 2012-08-03 14:07 | SignpostMarv | New Issue | |
| 2012-08-03 14:07 | SignpostMarv | File Added: osChat-objects-only.patch | |
| 2012-08-03 14:12 | SignpostMarv | File Added: osChat-test.oar | |
| 2012-08-03 14:12 | SignpostMarv | Note Added: 0021974 | |
| 2012-08-03 14:12 | SignpostMarv | Status | new => patch included |
| 2012-08-03 14:17 | SignpostMarv | Note Added: 0021975 | |
| 2012-08-03 16:14 | SignpostMarv | Note Added: 0021976 | |
| Copyright © 2000 - 2012 MantisBT Group |




