Merge branch 'master' of /home/opensim/var/repo/opensim

integration
BlueWall 2012-10-31 07:13:45 -04:00
commit 6a37f5f852
25 changed files with 655 additions and 324 deletions

View File

@ -306,6 +306,8 @@ namespace OpenSim.Framework
public AgentGroupData[] Groups; public AgentGroupData[] Groups;
public Animation[] Anims; public Animation[] Anims;
public Animation DefaultAnim = null;
public Animation AnimState = null;
public UUID GranterID; public UUID GranterID;
@ -390,6 +392,16 @@ namespace OpenSim.Framework
args["animations"] = anims; args["animations"] = anims;
} }
if (DefaultAnim != null)
{
args["default_animation"] = DefaultAnim.PackUpdateMessage();
}
if (AnimState != null)
{
args["animation_state"] = AnimState.PackUpdateMessage();
}
if (Appearance != null) if (Appearance != null)
args["packed_appearance"] = Appearance.Pack(); args["packed_appearance"] = Appearance.Pack();
@ -583,6 +595,30 @@ namespace OpenSim.Framework
} }
} }
if (args["default_animation"] != null)
{
try
{
DefaultAnim = new Animation((OSDMap)args["default_animation"]);
}
catch
{
DefaultAnim = null;
}
}
if (args["animation_state"] != null)
{
try
{
AnimState = new Animation((OSDMap)args["animation_state"]);
}
catch
{
AnimState = null;
}
}
//if ((args["agent_textures"] != null) && (args["agent_textures"]).Type == OSDType.Array) //if ((args["agent_textures"] != null) && (args["agent_textures"]).Type == OSDType.Array)
//{ //{
// OSDArray textures = (OSDArray)(args["agent_textures"]); // OSDArray textures = (OSDArray)(args["agent_textures"]);

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

@ -35,10 +35,12 @@ using OpenMetaverse;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
/// <summary> /// <summary>
/// A dictionary for task inventory. /// A dictionary containing task inventory items. Indexed by item UUID.
/// </summary> /// </summary>
/// <remarks>
/// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before
/// iterating over it. /// iterating over it.
/// </remarks>
public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>, public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>,
ICloneable, IXmlSerializable ICloneable, IXmlSerializable
{ {

View File

@ -73,9 +73,6 @@ namespace OpenSim.Framework
private bool _ownerChanged = false; private bool _ownerChanged = false;
// This used ONLY during copy. It can't be relied on at other times!
private bool _scriptRunning = true;
public UUID AssetID { public UUID AssetID {
get { get {
return _assetID; return _assetID;
@ -353,14 +350,13 @@ namespace OpenSim.Framework
} }
} }
public bool ScriptRunning { /// <summary>
get { /// This used ONLY during copy. It can't be relied on at other times!
return _scriptRunning; /// </summary>
} /// <remarks>
set { /// For true script running status, use IEntityInventory.TryGetScriptInstanceRunning() for now.
_scriptRunning = value; /// </remarks>
} public bool ScriptRunning { get; set; }
}
// See ICloneable // See ICloneable
@ -388,6 +384,7 @@ namespace OpenSim.Framework
public TaskInventoryItem() public TaskInventoryItem()
{ {
ScriptRunning = true;
CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
} }
} }

View File

@ -536,7 +536,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

@ -5219,8 +5219,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);

View File

@ -571,9 +571,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (grp.HasGroupChanged) if (grp.HasGroupChanged)
{ {
// m_log.DebugFormat( m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
// grp.UUID, grp.AttachmentPoint); grp.UUID, grp.AttachmentPoint);
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState);

View File

@ -606,12 +606,18 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
cdt.AddColumn("Asset UUID", 36); cdt.AddColumn("Asset UUID", 36);
foreach (TaskInventoryItem item in inv.GetInventoryItems()) foreach (TaskInventoryItem item in inv.GetInventoryItems())
{
bool foundScriptInstance, scriptRunning;
foundScriptInstance
= SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning);
cdt.AddRow( cdt.AddRow(
item.Name, item.Name,
((InventoryType)item.InvType).ToString(), ((InventoryType)item.InvType).ToString(),
(InventoryType)item.InvType == InventoryType.LSL ? item.ScriptRunning.ToString() : "n/a", foundScriptInstance ? scriptRunning.ToString() : "n/a",
item.ItemID.ToString(), item.ItemID.ToString(),
item.AssetID.ToString()); item.AssetID.ToString());
}
return sb.Append(cdt.ToString()); return sb.Append(cdt.ToString());
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -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

@ -149,6 +149,19 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="itemId"></param> /// <param name="itemId"></param>
void StopScriptInstance(UUID itemId); void StopScriptInstance(UUID itemId);
/// <summary>
/// Try to get the script running status.
/// </summary>
/// <returns>
/// Returns true if a script for the item was found in one of the simulator's script engines. In this case,
/// the running parameter will reflect the running status.
/// Returns false if the item could not be found, if the item is not a script or if a script instance for the
/// item was not found in any of the script engines. In this case, running status is irrelevant.
/// </returns>
/// <param name='itemId'></param>
/// <param name='running'></param>
bool TryGetScriptInstanceRunning(UUID itemId, out bool running);
/// <summary> /// <summary>
/// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
/// name is chosen. /// name is chosen.

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

@ -45,6 +45,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation();
private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>(); private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>();
public OpenSim.Framework.Animation DefaultAnimation
{
get { return m_defaultAnimation; }
}
public OpenSim.Framework.Animation ImplicitDefaultAnimation public OpenSim.Framework.Animation ImplicitDefaultAnimation
{ {
get { return m_implicitDefaultAnimation; } get { return m_implicitDefaultAnimation; }
@ -126,6 +131,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
return false; return false;
} }
// Called from serialization only
public void SetImplicitDefaultAnimation(UUID animID, int sequenceNum, UUID objectID)
{
m_implicitDefaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
}
protected bool ResetDefaultAnimation() protected bool ResetDefaultAnimation()
{ {
return TrySetDefaultAnimation("STAND", 1, UUID.Zero); return TrySetDefaultAnimation("STAND", 1, UUID.Zero);

View File

@ -1692,12 +1692,19 @@ namespace OpenSim.Region.Framework.Scenes
private void CheckAtTargets() private void CheckAtTargets()
{ {
Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; List<SceneObjectGroup> objs = null;
lock (m_groupsWithTargets)
objs = m_groupsWithTargets.Values;
foreach (SceneObjectGroup entry in objs) lock (m_groupsWithTargets)
entry.checkAtTargets(); {
if (m_groupsWithTargets.Count != 0)
objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
}
if (objs != null)
{
foreach (SceneObjectGroup entry in objs)
entry.checkAtTargets();
}
} }
/// <summary> /// <summary>
@ -3381,9 +3388,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

@ -2239,7 +2239,15 @@ namespace OpenSim.Region.Framework.Scenes
// play the sound. // play the sound.
if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f)
SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); {
ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
if (soundModule != null)
{
soundModule.SendSound(UUID, CollisionSound,
CollisionSoundVolume, true, (byte)0, 0, false,
false);
}
}
SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
@ -2287,37 +2295,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
lock (TaskInventory)
{
foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
{
if (item.Value.Name == sound)
{
soundID = item.Value.ItemID;
break;
}
}
}
}
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;
@ -2675,98 +2652,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
lock (TaskInventory)
{
foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
{
if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
{
soundID = item.Value.ItemID;
break;
}
}
}
}
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);
}
}
}
/// <summary> /// <summary>
/// Send a terse update to all clients /// Send a terse update to all clients
/// </summary> /// </summary>

View File

@ -232,31 +232,49 @@ namespace OpenSim.Region.Framework.Scenes
if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
return; return;
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null) // No engine at all
return;
lock (Items) lock (Items)
{ {
foreach (TaskInventoryItem item in Items.Values) foreach (TaskInventoryItem item in Items.Values)
{ {
if (item.InvType == (int)InventoryType.LSL) bool running;
{ if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running))
foreach (IScriptModule e in engines) item.ScriptRunning = running;
{
bool running;
if (e.HasScript(item.ItemID, out running))
{
item.ScriptRunning = running;
break;
}
}
}
} }
} }
} }
public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
{
running = false;
TaskInventoryItem item = GetInventoryItem(itemId);
if (item == null)
return false;
return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running);
}
public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running)
{
running = false;
if (item.InvType != (int)InventoryType.LSL)
return false;
IScriptModule[] engines = scene.RequestModuleInterfaces<IScriptModule>();
if (engines == null) // No engine at all
return false;
foreach (IScriptModule e in engines)
{
if (e.HasScript(item.ItemID, out running))
return true;
}
return false;
}
public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
{ {
int scriptsValidForStarting = 0; int scriptsValidForStarting = 0;

View File

@ -74,8 +74,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)
@ -3074,6 +3075,8 @@ namespace OpenSim.Region.Framework.Scenes
cAgent.Anims = Animator.Animations.ToArray(); cAgent.Anims = Animator.Animations.ToArray();
} }
catch { } catch { }
cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
if (Scene.AttachmentsModule != null) if (Scene.AttachmentsModule != null)
Scene.AttachmentsModule.CopyAttachments(this, cAgent); Scene.AttachmentsModule.CopyAttachments(this, cAgent);
@ -3145,6 +3148,10 @@ namespace OpenSim.Region.Framework.Scenes
// FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
if (cAgent.Anims != null) if (cAgent.Anims != null)
Animator.Animations.FromArray(cAgent.Anims); Animator.Animations.FromArray(cAgent.Anims);
if (cAgent.DefaultAnim != null)
Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
if (cAgent.AnimState != null)
Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
if (Scene.AttachmentsModule != null) if (Scene.AttachmentsModule != null)
Scene.AttachmentsModule.CopyAttachments(cAgent, this); Scene.AttachmentsModule.CopyAttachments(cAgent, this);

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

@ -3335,7 +3335,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)
@ -3345,14 +3344,14 @@ 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 != null && asset.Data != null && asset.Data.Length > 0)
{ {
if (!_pbs.SculptEntry) if (!_pbs.SculptEntry)
return; return;
@ -3365,6 +3364,12 @@ Console.WriteLine(" JointCreateFixed");
m_taintshape = true; m_taintshape = true;
_parent_scene.AddPhysicsActorTaint(this); _parent_scene.AddPhysicsActorTaint(this);
} }
else
{
m_log.WarnFormat(
"[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}",
_pbs.SculptTexture, Name, _position, _parent_scene.Name);
}
} }
} }
} }

View File

@ -107,6 +107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected IUrlModule m_UrlModule = null; protected IUrlModule m_UrlModule = null;
protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 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;
public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
{ {
@ -119,6 +120,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);
} }
@ -331,6 +333,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)
{ {
@ -2044,8 +2082,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()
@ -2365,63 +2402,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)
@ -2438,61 +2444,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);
} }
@ -4358,16 +4342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// 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;
} }
@ -5890,10 +5865,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

@ -26,9 +26,11 @@
*/ */
using System; using System;
using System.Runtime.Serialization;
namespace OpenSim.Region.ScriptEngine.Shared namespace OpenSim.Region.ScriptEngine.Shared
{ {
[Serializable]
public class ScriptException : Exception public class ScriptException : Exception
{ {
public ScriptException() : base() {} public ScriptException() : base() {}
@ -36,5 +38,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
public ScriptException(string message) : base(message) {} public ScriptException(string message) : base(message) {}
public ScriptException(string message, Exception innerException) : base(message, innerException) {} public ScriptException(string message, Exception innerException) : base(message, innerException) {}
public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {}
} }
} }

View File

@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
// log4net.Config.XmlConfigurator.Configure(); // log4net.Config.XmlConfigurator.Configure();
UUID userId = TestHelpers.ParseTail(0x1); UUID userId = TestHelpers.ParseTail(0x1);
// UUID objectId = TestHelpers.ParseTail(0x2); // UUID objectId = TestHelpers.ParseTail(0x100);
// UUID itemId = TestHelpers.ParseTail(0x3); // UUID itemId = TestHelpers.ParseTail(0x3);
string itemName = "TestStartScript() Item"; string itemName = "TestStartScript() Item";
@ -105,12 +105,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
m_scene.RezNewScript(userId, itemTemplate); SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate);
m_chatEvent.WaitOne(60000); m_chatEvent.WaitOne(60000);
Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()");
Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running"));
bool running;
TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
Assert.That(
SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
Assert.That(running, Is.True);
} }
private void OnChatFromWorld(object sender, OSChatMessage oscm) private void OnChatFromWorld(object sender, OSChatMessage oscm)

View File

@ -68,7 +68,11 @@ namespace OpenSim.Services.Interfaces
/// </summary> /// </summary>
/// <param name="id">The asset id</param> /// <param name="id">The asset id</param>
/// <param name="sender">Represents the requester. Passed back via the handler</param> /// <param name="sender">Represents the requester. Passed back via the handler</param>
/// <param name="handler">The handler to call back once the asset has been retrieved</param> /// <param name="handler">
/// The handler to call back once the asset has been retrieved. This will be called back with a null AssetBase
/// if the asset could not be found for some reason (e.g. if it does not exist, if a remote asset service
/// was not contactable, if it is not in the database, etc.).
/// </param>
/// <returns>True if the id was parseable, false otherwise</returns> /// <returns>True if the id was parseable, false otherwise</returns>
bool Get(string id, Object sender, AssetRetrieved handler); bool Get(string id, Object sender, AssetRetrieved handler);

View File

@ -1687,5 +1687,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"