Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
avinationmerge
Melanie 2012-10-30 01:02:20 +00:00
commit 48569e856a
13 changed files with 486 additions and 308 deletions

View File

@ -192,8 +192,19 @@ namespace OpenSim.Framework.Servers
"threads show", "threads show",
"Show thread status. Synonym for \"show threads\"", "Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport())); (string module, string[] args) => Notice(GetThreadsReport()));
m_console.Commands.AddCommand("General", false, "force gc",
"force gc",
"Manually invoke runtime garbage collection. For debugging purposes",
HandleForceGc);
} }
} }
private void HandleForceGc(string module, string[] args)
{
MainConsole.Instance.Output("Manually invoking runtime garbage collection");
GC.Collect();
}
/// <summary> /// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing

View File

@ -548,7 +548,7 @@ namespace OpenSim.Framework
/// <summary> /// <summary>
/// Determines whether a point is inside a bounding box. /// Determines whether a point is inside a bounding box.
/// </summary> /// </summary>
/// <param name='v'>/param> /// <param name='v'></param>
/// <param name='min'></param> /// <param name='min'></param>
/// <param name='max'></param> /// <param name='max'></param>
/// <returns></returns> /// <returns></returns>

View File

@ -1111,7 +1111,7 @@ namespace OpenSim
aCircuit.Name, aCircuit.Name,
aCircuit.child ? "child" : "root", aCircuit.child ? "child" : "root",
aCircuit.circuitcode.ToString(), aCircuit.circuitcode.ToString(),
aCircuit.IPAddress.ToString(), aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
aCircuit.Viewer); aCircuit.Viewer);
}); });

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.
* *
@ -24,56 +24,110 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
using log4net;
using Mono.Addins;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using System.Reflection;
using log4net;
namespace OpenSim.Region.CoreModules.World.Sound namespace OpenSim.Region.CoreModules.World.Sound
{ {
public class SoundModule : IRegionModule, ISoundModule [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
public class SoundModule : INonSharedRegionModule, ISoundModule
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
protected Scene m_scene;
private Scene m_scene;
public void Initialise(Scene scene, IConfigSource source)
public bool Enabled { get; private set; }
public float MaxDistance { get; private set; }
#region INonSharedRegionModule
public void Initialise(IConfigSource configSource)
{ {
IConfig config = configSource.Configs["Sounds"];
if (config == null)
{
Enabled = true;
MaxDistance = 100.0f;
}
else
{
Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") ==
Path.GetFileName(Assembly.GetExecutingAssembly().Location)
+ ":" + MethodBase.GetCurrentMethod().DeclaringType.Name;
MaxDistance = config.GetFloat("MaxDistance", 100.0f);
}
}
public void AddRegion(Scene scene) { }
public void RemoveRegion(Scene scene)
{
m_scene.EventManager.OnClientLogin -= OnNewClient;
}
public void RegionLoaded(Scene scene)
{
if (!Enabled)
return;
m_scene = scene; m_scene = scene;
m_scene.EventManager.OnClientLogin += OnNewClient;
m_scene.EventManager.OnNewClient += OnNewClient;
m_scene.RegisterModuleInterface<ISoundModule>(this); m_scene.RegisterModuleInterface<ISoundModule>(this);
} }
public void PostInitialise() {} public void Close() { }
public void Close() {}
public Type ReplaceableInterface
{
get { return typeof(ISoundModule); }
}
public string Name { get { return "Sound Module"; } } public string Name { get { return "Sound Module"; } }
public bool IsSharedModule { get { return false; } }
#endregion
#region Event Handlers
private void OnNewClient(IClientAPI client) private void OnNewClient(IClientAPI client)
{ {
client.OnSoundTrigger += TriggerSound; client.OnSoundTrigger += TriggerSound;
} }
#endregion
#region ISoundModule
public virtual void PlayAttachedSound( public virtual void PlayAttachedSound(
UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius)
{ {
SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); SceneObjectPart part;
if (part == null) if (!m_scene.TryGetSceneObjectPart(objectID, out part))
return; return;
SceneObjectGroup grp = part.ParentGroup; SceneObjectGroup grp = part.ParentGroup;
if (radius == 0)
radius = MaxDistance;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{ {
double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
if (dis > 100.0) // Max audio distance if (dis > MaxDistance) // Max audio distance
return; return;
if (grp.IsAttachment) if (grp.IsAttachment)
@ -85,26 +139,22 @@ namespace OpenSim.Region.CoreModules.World.Sound
dis = 0; dis = 0;
} }
float thisSpGain;
// Scale by distance // Scale by distance
if (radius == 0) double thisSpGain = gain * ((radius - dis) / radius);
thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
else
thisSpGain = (float)((double)gain * ((radius - dis) / radius));
sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
ownerID, (float)thisSpGain, flags);
}); });
} }
public virtual void TriggerSound( public virtual void TriggerSound(
UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
{ {
SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); SceneObjectPart part;
if (part == null) if (!m_scene.TryGetSceneObjectPart(objectID, out part))
{ {
ScenePresence sp; ScenePresence sp;
if (!m_scene.TryGetScenePresence(objectID, out sp)) if (!m_scene.TryGetScenePresence(ownerID, out sp))
return; return;
} }
else else
@ -118,24 +168,207 @@ namespace OpenSim.Region.CoreModules.World.Sound
} }
} }
if (radius == 0)
radius = MaxDistance;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{ {
double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
if (dis > 100.0) // Max audio distance if (dis > MaxDistance) // Max audio distance
return; return;
float thisSpGain;
// Scale by distance // Scale by distance
if (radius == 0) double thisSpGain = gain * ((radius - dis) / radius);
thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
else
thisSpGain = (float)((double)gain * ((radius - dis) / radius));
sp.ControllingClient.SendTriggeredSound( sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
soundId, ownerID, objectID, parentID, handle, position, thisSpGain); objectID, parentID, handle, position,
(float)thisSpGain);
}); });
} }
public virtual void StopSound(UUID objectID)
{
SceneObjectPart m_host;
if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
return;
StopSound(m_host);
}
private static void StopSound(SceneObjectPart m_host)
{
m_host.AdjustSoundGain(0);
// Xantor 20080528: Clear prim data of sound instead
if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
{
if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
{
foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
{
part.Sound = UUID.Zero;
part.SoundFlags = 1 << 5;
part.SoundRadius = 0;
part.ScheduleFullUpdate();
part.SendFullUpdateToAllClients();
}
m_host.ParentGroup.LoopSoundMasterPrim = null;
m_host.ParentGroup.LoopSoundSlavePrims.Clear();
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundFlags = 1 << 5;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundFlags = 1 << 5;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
}
public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
{
SceneObjectPart part;
if (soundID == UUID.Zero
|| !m_scene.TryGetSceneObjectPart(objectID, out part))
{
return;
}
if (radius == 0)
radius = MaxDistance;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance))
sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
});
}
// Xantor 20080528 we should do this differently.
// 1) apply the sound to the object
// 2) schedule full update
// just sending the sound out once doesn't work so well when other avatars come in view later on
// or when the prim gets moved, changed, sat on, whatever
// see large number of mantises (mantes?)
// 20080530 Updated to remove code duplication
// 20080530 Stop sound if there is one, otherwise volume only changes don't work
public void LoopSound(UUID objectID, UUID soundID,
double volume, double radius, bool isMaster)
{
SceneObjectPart m_host;
if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
return;
if (isMaster)
m_host.ParentGroup.LoopSoundMasterPrim = m_host;
if (m_host.Sound != UUID.Zero)
StopSound(m_host);
m_host.Sound = soundID;
m_host.SoundGain = volume;
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = radius;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
public void SendSound(UUID objectID, UUID soundID, double volume,
bool triggered, byte flags, float radius, bool useMaster,
bool isMaster)
{
if (soundID == UUID.Zero)
return;
SceneObjectPart part;
if (!m_scene.TryGetSceneObjectPart(objectID, out part))
return;
volume = Util.Clip((float)volume, 0, 1);
UUID parentID = part.ParentGroup.UUID;
Vector3 position = part.AbsolutePosition; // region local
ulong regionHandle = m_scene.RegionInfo.RegionHandle;
if (useMaster)
{
if (isMaster)
{
if (triggered)
TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
part.ParentGroup.PlaySoundMasterPrim = part;
if (triggered)
TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
{
position = prim.AbsolutePosition; // region local
if (triggered)
TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
}
part.ParentGroup.PlaySoundSlavePrims.Clear();
part.ParentGroup.PlaySoundMasterPrim = null;
}
else
{
part.ParentGroup.PlaySoundSlavePrims.Add(part);
}
}
else
{
if (triggered)
TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
else
PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
}
}
public void TriggerSoundLimited(UUID objectID, UUID sound,
double volume, Vector3 min, Vector3 max)
{
if (sound == UUID.Zero)
return;
SceneObjectPart part;
if (!m_scene.TryGetSceneObjectPart(objectID, out part))
return;
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
double dis = Util.GetDistanceTo(sp.AbsolutePosition,
part.AbsolutePosition);
if (dis > MaxDistance) // Max audio distance
return;
else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max))
return;
// Scale by distance
double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance);
sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID,
part.UUID, part.ParentGroup.UUID,
m_scene.RegionInfo.RegionHandle,
part.AbsolutePosition, (float)thisSpGain);
});
}
#endregion
} }
} }

View File

@ -32,9 +32,96 @@ namespace OpenSim.Region.Framework.Interfaces
{ {
public interface ISoundModule public interface ISoundModule
{ {
void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); /// <summary>
/// Maximum distance between a sound source and a recipient.
/// </summary>
float MaxDistance { get; }
/// <summary>
/// Play a sound from an object.
/// </summary>
/// <param name="soundID">Sound asset ID</param>
/// <param name="ownerID">Sound source owner</param>
/// <param name="objectID">Sound source ID</param>
/// <param name="gain">Sound volume</param>
/// <param name="position">Sound source position</param>
/// <param name="flags">Sound flags</param>
/// <param name="radius">
/// Radius used to affect gain over distance.
/// </param>
void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID,
double gain, Vector3 position, byte flags, float radius);
/// <summary>
/// Trigger a sound in the scene.
/// </summary>
/// <param name="soundId">Sound asset ID</param>
/// <param name="ownerID">Sound source owner</param>
/// <param name="objectID">Sound source ID</param>
/// <param name="parentID">Sound source parent.</param>
/// <param name="gain">Sound volume</param>
/// <param name="position">Sound source position</param>
/// <param name="handle"></param>
/// <param name="radius">
/// Radius used to affect gain over distance.
/// </param>
void TriggerSound( void TriggerSound(
UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); UUID soundId, UUID ownerID, UUID objectID, UUID parentID,
double gain, Vector3 position, UInt64 handle, float radius);
/// <summary>
/// Stop sounds eminating from an object.
/// </summary>
/// <param name="objectID">Sound source ID</param>
void StopSound(UUID objectID);
/// <summary>
/// Preload sound to viewers within range.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="soundID">Sound asset ID</param>
/// <param name="radius">
/// Radius used to determine which viewers should preload the sound.
/// </param>
void PreloadSound(UUID objectID, UUID soundID, float radius);
/// <summary>
/// Loop specified sound at specified volume with specified radius,
/// optionally declaring object as new sync master.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="soundID">Sound asset ID</param>
/// <param name="gain">Sound volume</param>
/// <param name="radius">Sound radius</param>
/// <param name="isMaster">Set object to sync master if true</param>
void LoopSound(UUID objectID, UUID soundID, double gain,
double radius, bool isMaster);
/// <summary>
/// Trigger or play an attached sound in this part's inventory.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="sound">Sound asset ID</param>
/// <param name="volume">Sound volume</param>
/// <param name="triggered">Triggered or not.</param>
/// <param name="flags"></param>
/// <param name="radius">Sound radius</param>
/// <param name="useMaster">Play using sound master</param>
/// <param name="isMaster">Play as sound master</param>
void SendSound(UUID objectID, UUID sound, double volume,
bool triggered, byte flags, float radius, bool useMaster,
bool isMaster);
/// <summary>
/// Trigger a sound to be played to all agents within an axis-aligned
/// bounding box.
/// </summary>
/// <param name="objectID">Sound source ID</param>
/// <param name="sound">Sound asset ID</param>
/// <param name="volume">Sound volume</param>
/// <param name="min">AABB bottom south-west corner</param>
/// <param name="max">AABB top north-east corner</param>
void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
Vector3 min, Vector3 max);
} }
} }

View File

@ -3552,9 +3552,10 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
// We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
// simultaneously. // simultaneously.
m_authenticateHandler.RemoveCircuit(acd.circuitcode); // We also need to remove by agent ID since NPCs will have no circuit code.
m_authenticateHandler.RemoveCircuit(agentID);
} }
} }

View File

@ -2895,38 +2895,6 @@ namespace OpenSim.Region.Framework.Scenes
ScheduleTerseUpdate(); ScheduleTerseUpdate();
} }
public void PreloadSound(string sound)
{
// UUID ownerID = OwnerID;
UUID objectID = ParentGroup.RootPart.UUID;
UUID soundID = UUID.Zero;
if (!UUID.TryParse(sound, out soundID))
{
//Trys to fetch sound id from prim's inventory.
//Prim's inventory doesn't support non script items yet
TaskInventory.LockItemsForRead(true);
foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
{
if (item.Value.Name == sound)
{
soundID = item.Value.ItemID;
break;
}
}
TaskInventory.LockItemsForRead(false);
}
ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100))
sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
});
}
public void RemFlag(PrimFlags flag) public void RemFlag(PrimFlags flag)
{ {
// PrimFlags prevflag = Flags; // PrimFlags prevflag = Flags;
@ -3297,126 +3265,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// Trigger or play an attached sound in this part's inventory.
/// </summary>
/// <param name="sound"></param>
/// <param name="volume"></param>
/// <param name="triggered"></param>
/// <param name="flags"></param>
public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster)
{
if (volume > 1)
volume = 1;
if (volume < 0)
volume = 0;
UUID ownerID = OwnerID;
UUID objectID = ParentGroup.RootPart.UUID;
UUID parentID = ParentGroup.UUID;
UUID soundID = UUID.Zero;
Vector3 position = AbsolutePosition; // region local
ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
if (!UUID.TryParse(sound, out soundID))
{
// search sound file from inventory
TaskInventory.LockItemsForRead(true);
foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
{
if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
{
soundID = item.Value.ItemID;
break;
}
}
TaskInventory.LockItemsForRead(false);
}
if (soundID == UUID.Zero)
return;
ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
if (soundModule != null)
{
if (useMaster)
{
if (isMaster)
{
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
ParentGroup.PlaySoundMasterPrim = this;
ownerID = OwnerID;
objectID = ParentGroup.RootPart.UUID;
parentID = ParentGroup.UUID;
position = AbsolutePosition; // region local
regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims)
{
ownerID = prim.OwnerID;
objectID = prim.ParentGroup.RootPart.UUID;
parentID = prim.ParentGroup.UUID;
position = prim.AbsolutePosition; // region local
regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle;
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
}
ParentGroup.PlaySoundSlavePrims.Clear();
ParentGroup.PlaySoundMasterPrim = null;
}
else
{
ParentGroup.PlaySoundSlavePrims.Add(this);
}
}
else
{
if (triggered)
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
else
soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
}
}
}
public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
{
if (soundID == UUID.Zero)
return;
ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
if (soundModule == null)
return;
if (volume > 1)
volume = 1;
if (volume < 0)
volume = 0;
int now = Util.EnvironmentTickCount();
if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
return;
LastColSoundSentTime = now;
UUID ownerID = OwnerID;
UUID objectID = ParentGroup.RootPart.UUID;
UUID parentID = ParentGroup.UUID;
ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
}
/// <summary> /// <summary>
/// Send a terse update to all clients /// Send a terse update to all clients
/// </summary> /// </summary>

View File

@ -75,8 +75,9 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// ~ScenePresence() // ~ScenePresence()
// { // {
// m_log.Debug("[SCENE PRESENCE] Destructor called"); // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
// } // }
private void TriggerScenePresenceUpdated() private void TriggerScenePresenceUpdated()
{ {
if (m_scene != null) if (m_scene != null)

View File

@ -821,8 +821,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
{ {
if (!CanEdit()) if (!CanEdit())
return; return;
ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>();
GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); if (module != null)
{
module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false);
}
} }
#endregion #endregion

View File

@ -117,6 +117,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
Assert.That(npc, Is.Not.Null); Assert.That(npc, Is.Not.Null);
Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId));
Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname)));
IClientAPI client;
Assert.That(m_scene.TryGetClient(npcId, out client), Is.True);
// Have to account for both SP and NPC.
Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2));
} }
[Test] [Test]
@ -136,6 +142,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); ScenePresence deletedNpc = m_scene.GetScenePresence(npcId);
Assert.That(deletedNpc, Is.Null); Assert.That(deletedNpc, Is.Null);
IClientAPI client;
Assert.That(m_scene.TryGetClient(npcId, out client), Is.False);
// Have to account for SP still present.
Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
} }
[Test] [Test]

View File

@ -3341,7 +3341,6 @@ Console.WriteLine(" JointCreateFixed");
m_material = pMaterial; m_material = pMaterial;
} }
private void CheckMeshAsset() private void CheckMeshAsset()
{ {
if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
@ -3351,12 +3350,12 @@ Console.WriteLine(" JointCreateFixed");
{ {
RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
if (assetProvider != null) if (assetProvider != null)
assetProvider(_pbs.SculptTexture, MeshAssetReveived); assetProvider(_pbs.SculptTexture, MeshAssetReceived);
}); });
} }
} }
void MeshAssetReveived(AssetBase asset) private void MeshAssetReceived(AssetBase asset)
{ {
if (asset.Data != null && asset.Data.Length > 0) if (asset.Data != null && asset.Data.Length > 0)
{ {

View File

@ -113,6 +113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
new Dictionary<UUID, UserInfoCacheEntry>(); new Dictionary<UUID, UserInfoCacheEntry>();
protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
protected ISoundModule m_SoundModule = null;
// protected Timer m_ShoutSayTimer; // protected Timer m_ShoutSayTimer;
protected int m_SayShoutCount = 0; protected int m_SayShoutCount = 0;
@ -160,6 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_TransferModule = m_TransferModule =
m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
AsyncCommands = new AsyncCommandManager(ScriptEngine); AsyncCommands = new AsyncCommandManager(ScriptEngine);
} }
@ -427,6 +429,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return key; return key;
} }
/// <summary>
/// Return the UUID of the asset matching the specified key or name
/// and asset type.
/// </summary>
/// <param name="k"></param>
/// <param name="type"></param>
/// <returns></returns>
protected UUID KeyOrName(string k, AssetType type)
{
UUID key;
if (!UUID.TryParse(k, out key))
{
TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
if (item != null && item.Type == (int)type)
key = item.AssetID;
}
else
{
lock (m_host.TaskInventory)
{
foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory)
{
if (item.Value.Type == (int)type && item.Value.Name == k)
{
key = item.Value.ItemID;
break;
}
}
}
}
return key;
}
//These are the implementations of the various ll-functions used by the LSL scripts. //These are the implementations of the various ll-functions used by the LSL scripts.
public LSL_Float llSin(double f) public LSL_Float llSin(double f)
{ {
@ -2279,8 +2317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Vector llGetPos() public LSL_Vector llGetPos()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
Vector3 pos = m_host.GetWorldPosition(); return m_host.GetWorldPosition();
return new LSL_Vector(pos.X, pos.Y, pos.Z);
} }
public LSL_Vector llGetLocalPos() public LSL_Vector llGetLocalPos()
@ -2638,63 +2675,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// send the sound, once, to all clients in range // send the sound, once, to all clients in range
m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); if (m_SoundModule != null)
{
m_SoundModule.SendSound(m_host.UUID,
KeyOrName(sound, AssetType.Sound), volume, false, 0,
0, false, false);
}
} }
// Xantor 20080528 we should do this differently.
// 1) apply the sound to the object
// 2) schedule full update
// just sending the sound out once doesn't work so well when other avatars come in view later on
// or when the prim gets moved, changed, sat on, whatever
// see large number of mantises (mantes?)
// 20080530 Updated to remove code duplication
// 20080530 Stop sound if there is one, otherwise volume only changes don't work
public void llLoopSound(string sound, double volume) public void llLoopSound(string sound, double volume)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (m_SoundModule != null)
if (m_host.Sound != UUID.Zero) {
llStopSound(); m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
volume, 20, false);
m_host.Sound = KeyOrName(sound); }
m_host.SoundGain = volume;
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
} }
public void llLoopSoundMaster(string sound, double volume) public void llLoopSoundMaster(string sound, double volume)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
m_host.ParentGroup.LoopSoundMasterPrim = m_host; if (m_SoundModule != null)
lock (m_host.ParentGroup.LoopSoundSlavePrims)
{ {
foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
{ volume, 20, true);
if (prim.Sound != UUID.Zero)
llStopSound();
prim.Sound = KeyOrName(sound);
prim.SoundGain = volume;
prim.SoundFlags = 1; // looping
prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
prim.ScheduleFullUpdate();
prim.SendFullUpdateToAllClients();
}
} }
if (m_host.Sound != UUID.Zero)
llStopSound();
m_host.Sound = KeyOrName(sound);
m_host.SoundGain = volume;
m_host.SoundFlags = 1; // looping
m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
} }
public void llLoopSoundSlave(string sound, double volume) public void llLoopSoundSlave(string sound, double volume)
@ -2711,61 +2717,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// send the sound, once, to all clients in range // send the sound, once, to all clients in range
m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); if (m_SoundModule != null)
{
m_SoundModule.SendSound(m_host.UUID,
KeyOrName(sound, AssetType.Sound), volume, false, 0,
0, true, false);
}
} }
public void llTriggerSound(string sound, double volume) public void llTriggerSound(string sound, double volume)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// send the sound, once, to all clients in range // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); if (m_SoundModule != null)
{
m_SoundModule.SendSound(m_host.UUID,
KeyOrName(sound, AssetType.Sound), volume, true, 0, 0,
false, false);
}
} }
// Xantor 20080528: Clear prim data of sound instead
public void llStopSound() public void llStopSound()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
{ if (m_SoundModule != null)
if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) m_SoundModule.StopSound(m_host.UUID);
{
foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
{
part.Sound = UUID.Zero;
part.SoundGain = 0;
part.SoundFlags = 0;
part.SoundRadius = 0;
part.ScheduleFullUpdate();
part.SendFullUpdateToAllClients();
}
m_host.ParentGroup.LoopSoundMasterPrim = null;
m_host.ParentGroup.LoopSoundSlavePrims.Clear();
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundGain = 0;
m_host.SoundFlags = 0;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
}
else
{
m_host.Sound = UUID.Zero;
m_host.SoundGain = 0;
m_host.SoundFlags = 0;
m_host.SoundRadius = 0;
m_host.ScheduleFullUpdate();
m_host.SendFullUpdateToAllClients();
}
} }
public void llPreloadSound(string sound) public void llPreloadSound(string sound)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
m_host.PreloadSound(sound); if (m_SoundModule != null)
m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0);
ScriptSleep(1000); ScriptSleep(1000);
} }
@ -4747,16 +4731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
} }
// TODO: Parameter check logic required. // TODO: Parameter check logic required.
UUID soundId = UUID.Zero; m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound);
if (!UUID.TryParse(impact_sound, out soundId))
{
TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound);
if (item != null && item.Type == (int)AssetType.Sound)
soundId = item.AssetID;
}
m_host.CollisionSound = soundId;
m_host.CollisionSoundVolume = (float)impact_volume; m_host.CollisionSoundVolume = (float)impact_volume;
m_host.CollisionSoundType = 1; m_host.CollisionSoundType = 1;
} }
@ -6318,10 +6293,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSL_Vector bottom_south_west) LSL_Vector bottom_south_west)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
float radius1 = (float)llVecDist(llGetPos(), top_north_east); if (m_SoundModule != null)
float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); {
float radius = Math.Abs(radius1 - radius2); m_SoundModule.TriggerSoundLimited(m_host.UUID,
m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); KeyOrName(sound, AssetType.Sound), volume,
bottom_south_west, top_north_east);
}
} }
public void llEjectFromLand(string pest) public void llEjectFromLand(string pest)

View File

@ -1683,5 +1683,12 @@ Enabled = False
;; default is module is disabled at the top level ;; default is module is disabled at the top level
AutoBackupModuleEnabled = false AutoBackupModuleEnabled = false
[Sounds]
;; {Module} {} {Implementation of ISoundModule to use.} {OpenSim.Region.CoreModules.dll:SoundModule}
Module = OpenSim.Region.CoreModules.dll:SoundModule
;; {MaxDistance} {} {Cut-off distance at which sounds will not be sent to users} {100.0}
MaxDistance = 100.0
[Modules] [Modules]
Include-modules = "addon-modules/*/config/*.ini" Include-modules = "addon-modules/*/config/*.ini"