aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs11
-rw-r--r--OpenSim/Framework/Util.cs2
-rw-r--r--OpenSim/Region/Application/OpenSim.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs315
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs93
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs152
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs3
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs7
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs11
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs179
-rw-r--r--bin/OpenSimDefaults.ini7
13 files changed, 485 insertions, 307 deletions
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index a8f3a9e..605909d 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -192,8 +192,19 @@ namespace OpenSim.Framework.Servers
192 "threads show", 192 "threads show",
193 "Show thread status. Synonym for \"show threads\"", 193 "Show thread status. Synonym for \"show threads\"",
194 (string module, string[] args) => Notice(GetThreadsReport())); 194 (string module, string[] args) => Notice(GetThreadsReport()));
195
196 m_console.Commands.AddCommand("General", false, "force gc",
197 "force gc",
198 "Manually invoke runtime garbage collection. For debugging purposes",
199 HandleForceGc);
195 } 200 }
196 } 201 }
202
203 private void HandleForceGc(string module, string[] args)
204 {
205 MainConsole.Instance.Output("Manually invoking runtime garbage collection");
206 GC.Collect();
207 }
197 208
198 /// <summary> 209 /// <summary>
199 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing 210 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 74551ea..e76a37b 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -548,7 +548,7 @@ namespace OpenSim.Framework
548 /// <summary> 548 /// <summary>
549 /// Determines whether a point is inside a bounding box. 549 /// Determines whether a point is inside a bounding box.
550 /// </summary> 550 /// </summary>
551 /// <param name='v'>/param> 551 /// <param name='v'></param>
552 /// <param name='min'></param> 552 /// <param name='min'></param>
553 /// <param name='max'></param> 553 /// <param name='max'></param>
554 /// <returns></returns> 554 /// <returns></returns>
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 3d4dce1..5f07272 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -1111,7 +1111,7 @@ namespace OpenSim
1111 aCircuit.Name, 1111 aCircuit.Name,
1112 aCircuit.child ? "child" : "root", 1112 aCircuit.child ? "child" : "root",
1113 aCircuit.circuitcode.ToString(), 1113 aCircuit.circuitcode.ToString(),
1114 aCircuit.IPAddress.ToString(), 1114 aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
1115 aCircuit.Viewer); 1115 aCircuit.Viewer);
1116 }); 1116 });
1117 1117
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index a2f0950..513a8f5 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -24,56 +24,110 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
28using System; 27using System;
28using System.IO;
29using System.Collections.Generic;
30using System.Reflection;
31
29using Nini.Config; 32using Nini.Config;
30using OpenMetaverse; 33using OpenMetaverse;
34using log4net;
35using Mono.Addins;
36
31using OpenSim.Framework; 37using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
34using System.Reflection;
35using log4net;
36 40
37namespace OpenSim.Region.CoreModules.World.Sound 41namespace OpenSim.Region.CoreModules.World.Sound
38{ 42{
39 public class SoundModule : IRegionModule, ISoundModule 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
44 public class SoundModule : INonSharedRegionModule, ISoundModule
40 { 45 {
41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(
42 47 MethodBase.GetCurrentMethod().DeclaringType);
43 protected Scene m_scene; 48
44 49 private Scene m_scene;
45 public void Initialise(Scene scene, IConfigSource source) 50
51 public bool Enabled { get; private set; }
52
53 public float MaxDistance { get; private set; }
54
55 #region INonSharedRegionModule
56
57 public void Initialise(IConfigSource configSource)
58 {
59 IConfig config = configSource.Configs["Sounds"];
60
61 if (config == null)
62 {
63 Enabled = true;
64 MaxDistance = 100.0f;
65 }
66 else
67 {
68 Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") ==
69 Path.GetFileName(Assembly.GetExecutingAssembly().Location)
70 + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name;
71 MaxDistance = config.GetFloat("MaxDistance", 100.0f);
72 }
73 }
74
75 public void AddRegion(Scene scene) { }
76
77 public void RemoveRegion(Scene scene)
46 { 78 {
79 m_scene.EventManager.OnClientLogin -= OnNewClient;
80 }
81
82 public void RegionLoaded(Scene scene)
83 {
84 if (!Enabled)
85 return;
86
47 m_scene = scene; 87 m_scene = scene;
48 88 m_scene.EventManager.OnClientLogin += OnNewClient;
49 m_scene.EventManager.OnNewClient += OnNewClient; 89
50
51 m_scene.RegisterModuleInterface<ISoundModule>(this); 90 m_scene.RegisterModuleInterface<ISoundModule>(this);
52 } 91 }
53 92
54 public void PostInitialise() {} 93 public void Close() { }
55 public void Close() {} 94
95 public Type ReplaceableInterface
96 {
97 get { return typeof(ISoundModule); }
98 }
99
56 public string Name { get { return "Sound Module"; } } 100 public string Name { get { return "Sound Module"; } }
57 public bool IsSharedModule { get { return false; } } 101
58 102 #endregion
103
104 #region Event Handlers
105
59 private void OnNewClient(IClientAPI client) 106 private void OnNewClient(IClientAPI client)
60 { 107 {
61 client.OnSoundTrigger += TriggerSound; 108 client.OnSoundTrigger += TriggerSound;
62 } 109 }
63 110
111 #endregion
112
113 #region ISoundModule
114
64 public virtual void PlayAttachedSound( 115 public virtual void PlayAttachedSound(
65 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) 116 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius)
66 { 117 {
67 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); 118 SceneObjectPart part;
68 if (part == null) 119 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
69 return; 120 return;
70 121
71 SceneObjectGroup grp = part.ParentGroup; 122 SceneObjectGroup grp = part.ParentGroup;
72 123
124 if (radius == 0)
125 radius = MaxDistance;
126
73 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
74 { 128 {
75 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
76 if (dis > 100.0) // Max audio distance 130 if (dis > MaxDistance) // Max audio distance
77 return; 131 return;
78 132
79 if (grp.IsAttachment) 133 if (grp.IsAttachment)
@@ -85,26 +139,22 @@ namespace OpenSim.Region.CoreModules.World.Sound
85 dis = 0; 139 dis = 0;
86 } 140 }
87 141
88 float thisSpGain;
89
90 // Scale by distance 142 // Scale by distance
91 if (radius == 0) 143 double thisSpGain = gain * ((radius - dis) / radius);
92 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
93 else
94 thisSpGain = (float)((double)gain * ((radius - dis) / radius));
95 144
96 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); 145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
146 ownerID, (float)thisSpGain, flags);
97 }); 147 });
98 } 148 }
99 149
100 public virtual void TriggerSound( 150 public virtual void TriggerSound(
101 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
102 { 152 {
103 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); 153 SceneObjectPart part;
104 if (part == null) 154 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
105 { 155 {
106 ScenePresence sp; 156 ScenePresence sp;
107 if (!m_scene.TryGetScenePresence(objectID, out sp)) 157 if (!m_scene.TryGetScenePresence(ownerID, out sp))
108 return; 158 return;
109 } 159 }
110 else 160 else
@@ -118,24 +168,207 @@ namespace OpenSim.Region.CoreModules.World.Sound
118 } 168 }
119 } 169 }
120 170
171 if (radius == 0)
172 radius = MaxDistance;
173
121 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
122 { 175 {
123 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
124 177
125 if (dis > 100.0) // Max audio distance 178 if (dis > MaxDistance) // Max audio distance
126 return; 179 return;
127 180
128 float thisSpGain;
129
130 // Scale by distance 181 // Scale by distance
131 if (radius == 0) 182 double thisSpGain = gain * ((radius - dis) / radius);
132 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); 183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position,
186 (float)thisSpGain);
187 });
188 }
189
190 public virtual void StopSound(UUID objectID)
191 {
192 SceneObjectPart m_host;
193 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
194 return;
195
196 StopSound(m_host);
197 }
198
199 private static void StopSound(SceneObjectPart m_host)
200 {
201 m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
204 {
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
206 {
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
133 else 218 else
134 thisSpGain = (float)((double)gain * ((radius - dis) / radius)); 219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 }
135 236
136 sp.ControllingClient.SendTriggeredSound( 237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
137 soundId, ownerID, objectID, parentID, handle, position, thisSpGain); 238 {
239 SceneObjectPart part;
240 if (soundID == UUID.Zero
241 || !m_scene.TryGetSceneObjectPart(objectID, out part))
242 {
243 return;
244 }
245
246 if (radius == 0)
247 radius = MaxDistance;
248
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance))
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
138 }); 253 });
139 } 254 }
255
256 // Xantor 20080528 we should do this differently.
257 // 1) apply the sound to the object
258 // 2) schedule full update
259 // just sending the sound out once doesn't work so well when other avatars come in view later on
260 // or when the prim gets moved, changed, sat on, whatever
261 // see large number of mantises (mantes?)
262 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster)
266 {
267 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return;
270
271 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host;
273
274 if (m_host.Sound != UUID.Zero)
275 StopSound(m_host);
276
277 m_host.Sound = soundID;
278 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping
280 m_host.SoundRadius = radius;
281
282 m_host.ScheduleFullUpdate();
283 m_host.SendFullUpdateToAllClients();
284 }
285
286 public void SendSound(UUID objectID, UUID soundID, double volume,
287 bool triggered, byte flags, float radius, bool useMaster,
288 bool isMaster)
289 {
290 if (soundID == UUID.Zero)
291 return;
292
293 SceneObjectPart part;
294 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
295 return;
296
297 volume = Util.Clip((float)volume, 0, 1);
298
299 UUID parentID = part.ParentGroup.UUID;
300
301 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303
304 if (useMaster)
305 {
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
328 else
329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else
334 {
335 if (triggered)
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
337 else
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
339 }
340 }
341
342 public void TriggerSoundLimited(UUID objectID, UUID sound,
343 double volume, Vector3 min, Vector3 max)
344 {
345 if (sound == UUID.Zero)
346 return;
347
348 SceneObjectPart part;
349 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
350 return;
351
352 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
353 {
354 double dis = Util.GetDistanceTo(sp.AbsolutePosition,
355 part.AbsolutePosition);
356
357 if (dis > MaxDistance) // Max audio distance
358 return;
359 else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max))
360 return;
361
362 // Scale by distance
363 double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance);
364
365 sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID,
366 part.UUID, part.ParentGroup.UUID,
367 m_scene.RegionInfo.RegionHandle,
368 part.AbsolutePosition, (float)thisSpGain);
369 });
370 }
371
372 #endregion
140 } 373 }
141} 374}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 6117a80..68af492 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -32,9 +32,96 @@ namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface ISoundModule 33 public interface ISoundModule
34 { 34 {
35 void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); 35 /// <summary>
36 36 /// Maximum distance between a sound source and a recipient.
37 /// </summary>
38 float MaxDistance { get; }
39
40 /// <summary>
41 /// Play a sound from an object.
42 /// </summary>
43 /// <param name="soundID">Sound asset ID</param>
44 /// <param name="ownerID">Sound source owner</param>
45 /// <param name="objectID">Sound source ID</param>
46 /// <param name="gain">Sound volume</param>
47 /// <param name="position">Sound source position</param>
48 /// <param name="flags">Sound flags</param>
49 /// <param name="radius">
50 /// Radius used to affect gain over distance.
51 /// </param>
52 void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID,
53 double gain, Vector3 position, byte flags, float radius);
54
55 /// <summary>
56 /// Trigger a sound in the scene.
57 /// </summary>
58 /// <param name="soundId">Sound asset ID</param>
59 /// <param name="ownerID">Sound source owner</param>
60 /// <param name="objectID">Sound source ID</param>
61 /// <param name="parentID">Sound source parent.</param>
62 /// <param name="gain">Sound volume</param>
63 /// <param name="position">Sound source position</param>
64 /// <param name="handle"></param>
65 /// <param name="radius">
66 /// Radius used to affect gain over distance.
67 /// </param>
37 void TriggerSound( 68 void TriggerSound(
38 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); 69 UUID soundId, UUID ownerID, UUID objectID, UUID parentID,
70 double gain, Vector3 position, UInt64 handle, float radius);
71
72 /// <summary>
73 /// Stop sounds eminating from an object.
74 /// </summary>
75 /// <param name="objectID">Sound source ID</param>
76 void StopSound(UUID objectID);
77
78 /// <summary>
79 /// Preload sound to viewers within range.
80 /// </summary>
81 /// <param name="objectID">Sound source ID</param>
82 /// <param name="soundID">Sound asset ID</param>
83 /// <param name="radius">
84 /// Radius used to determine which viewers should preload the sound.
85 /// </param>
86 void PreloadSound(UUID objectID, UUID soundID, float radius);
87
88 /// <summary>
89 /// Loop specified sound at specified volume with specified radius,
90 /// optionally declaring object as new sync master.
91 /// </summary>
92 /// <param name="objectID">Sound source ID</param>
93 /// <param name="soundID">Sound asset ID</param>
94 /// <param name="gain">Sound volume</param>
95 /// <param name="radius">Sound radius</param>
96 /// <param name="isMaster">Set object to sync master if true</param>
97 void LoopSound(UUID objectID, UUID soundID, double gain,
98 double radius, bool isMaster);
99
100 /// <summary>
101 /// Trigger or play an attached sound in this part's inventory.
102 /// </summary>
103 /// <param name="objectID">Sound source ID</param>
104 /// <param name="sound">Sound asset ID</param>
105 /// <param name="volume">Sound volume</param>
106 /// <param name="triggered">Triggered or not.</param>
107 /// <param name="flags"></param>
108 /// <param name="radius">Sound radius</param>
109 /// <param name="useMaster">Play using sound master</param>
110 /// <param name="isMaster">Play as sound master</param>
111 void SendSound(UUID objectID, UUID sound, double volume,
112 bool triggered, byte flags, float radius, bool useMaster,
113 bool isMaster);
114
115 /// <summary>
116 /// Trigger a sound to be played to all agents within an axis-aligned
117 /// bounding box.
118 /// </summary>
119 /// <param name="objectID">Sound source ID</param>
120 /// <param name="sound">Sound asset ID</param>
121 /// <param name="volume">Sound volume</param>
122 /// <param name="min">AABB bottom south-west corner</param>
123 /// <param name="max">AABB top north-east corner</param>
124 void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
125 Vector3 min, Vector3 max);
39 } 126 }
40} \ No newline at end of file 127} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 9f87e1e..2066536 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3552,9 +3552,10 @@ namespace OpenSim.Region.Framework.Scenes
3552 } 3552 }
3553 else 3553 else
3554 { 3554 {
3555 // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred 3555 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3556 // simultaneously. 3556 // simultaneously.
3557 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 3557 // We also need to remove by agent ID since NPCs will have no circuit code.
3558 m_authenticateHandler.RemoveCircuit(agentID);
3558 } 3559 }
3559 } 3560 }
3560 3561
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 248679b..b7f4291 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2895,38 +2895,6 @@ namespace OpenSim.Region.Framework.Scenes
2895 ScheduleTerseUpdate(); 2895 ScheduleTerseUpdate();
2896 } 2896 }
2897 2897
2898 public void PreloadSound(string sound)
2899 {
2900 // UUID ownerID = OwnerID;
2901 UUID objectID = ParentGroup.RootPart.UUID;
2902 UUID soundID = UUID.Zero;
2903
2904 if (!UUID.TryParse(sound, out soundID))
2905 {
2906 //Trys to fetch sound id from prim's inventory.
2907 //Prim's inventory doesn't support non script items yet
2908
2909 TaskInventory.LockItemsForRead(true);
2910
2911 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2912 {
2913 if (item.Value.Name == sound)
2914 {
2915 soundID = item.Value.ItemID;
2916 break;
2917 }
2918 }
2919
2920 TaskInventory.LockItemsForRead(false);
2921 }
2922
2923 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
2924 {
2925 if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100))
2926 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
2927 });
2928 }
2929
2930 public void RemFlag(PrimFlags flag) 2898 public void RemFlag(PrimFlags flag)
2931 { 2899 {
2932 // PrimFlags prevflag = Flags; 2900 // PrimFlags prevflag = Flags;
@@ -3298,126 +3266,6 @@ namespace OpenSim.Region.Framework.Scenes
3298 } 3266 }
3299 3267
3300 /// <summary> 3268 /// <summary>
3301 /// Trigger or play an attached sound in this part's inventory.
3302 /// </summary>
3303 /// <param name="sound"></param>
3304 /// <param name="volume"></param>
3305 /// <param name="triggered"></param>
3306 /// <param name="flags"></param>
3307 public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster)
3308 {
3309 if (volume > 1)
3310 volume = 1;
3311 if (volume < 0)
3312 volume = 0;
3313
3314 UUID ownerID = OwnerID;
3315 UUID objectID = ParentGroup.RootPart.UUID;
3316 UUID parentID = ParentGroup.UUID;
3317
3318 UUID soundID = UUID.Zero;
3319 Vector3 position = AbsolutePosition; // region local
3320 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3321
3322 if (!UUID.TryParse(sound, out soundID))
3323 {
3324 // search sound file from inventory
3325 TaskInventory.LockItemsForRead(true);
3326 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3327 {
3328 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3329 {
3330 soundID = item.Value.ItemID;
3331 break;
3332 }
3333 }
3334 TaskInventory.LockItemsForRead(false);
3335 }
3336
3337 if (soundID == UUID.Zero)
3338 return;
3339
3340 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3341 if (soundModule != null)
3342 {
3343 if (useMaster)
3344 {
3345 if (isMaster)
3346 {
3347 if (triggered)
3348 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3349 else
3350 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3351 ParentGroup.PlaySoundMasterPrim = this;
3352 ownerID = OwnerID;
3353 objectID = ParentGroup.RootPart.UUID;
3354 parentID = ParentGroup.UUID;
3355 position = AbsolutePosition; // region local
3356 regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3357 if (triggered)
3358 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3359 else
3360 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3361 foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims)
3362 {
3363 ownerID = prim.OwnerID;
3364 objectID = prim.ParentGroup.RootPart.UUID;
3365 parentID = prim.ParentGroup.UUID;
3366 position = prim.AbsolutePosition; // region local
3367 regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle;
3368 if (triggered)
3369 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3370 else
3371 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3372 }
3373 ParentGroup.PlaySoundSlavePrims.Clear();
3374 ParentGroup.PlaySoundMasterPrim = null;
3375 }
3376 else
3377 {
3378 ParentGroup.PlaySoundSlavePrims.Add(this);
3379 }
3380 }
3381 else
3382 {
3383 if (triggered)
3384 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3385 else
3386 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3387 }
3388 }
3389 }
3390
3391 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3392 {
3393 if (soundID == UUID.Zero)
3394 return;
3395
3396 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3397 if (soundModule == null)
3398 return;
3399
3400 if (volume > 1)
3401 volume = 1;
3402 if (volume < 0)
3403 volume = 0;
3404
3405 int now = Util.EnvironmentTickCount();
3406 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3407 return;
3408
3409 LastColSoundSentTime = now;
3410
3411 UUID ownerID = OwnerID;
3412 UUID objectID = ParentGroup.RootPart.UUID;
3413 UUID parentID = ParentGroup.UUID;
3414 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3415
3416 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3417 }
3418
3419
3420 /// <summary>
3421 /// Send a terse update to all clients 3269 /// Send a terse update to all clients
3422 /// </summary> 3270 /// </summary>
3423 public void SendTerseUpdateToAllClients() 3271 public void SendTerseUpdateToAllClients()
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 870bd66..285d1ae 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -75,8 +75,9 @@ namespace OpenSim.Region.Framework.Scenes
75 { 75 {
76// ~ScenePresence() 76// ~ScenePresence()
77// { 77// {
78// m_log.Debug("[SCENE PRESENCE] Destructor called"); 78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 79// }
80
80 private void TriggerScenePresenceUpdated() 81 private void TriggerScenePresenceUpdated()
81 { 82 {
82 if (m_scene != null) 83 if (m_scene != null)
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index aa23fee..5ed1514 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -821,8 +821,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
821 { 821 {
822 if (!CanEdit()) 822 if (!CanEdit())
823 return; 823 return;
824 824 ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>();
825 GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); 825 if (module != null)
826 {
827 module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false);
828 }
826 } 829 }
827 830
828 #endregion 831 #endregion
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 9179966..52ed846 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -117,6 +117,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
117 Assert.That(npc, Is.Not.Null); 117 Assert.That(npc, Is.Not.Null);
118 Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); 118 Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId));
119 Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); 119 Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname)));
120
121 IClientAPI client;
122 Assert.That(m_scene.TryGetClient(npcId, out client), Is.True);
123
124 // Have to account for both SP and NPC.
125 Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2));
120 } 126 }
121 127
122 [Test] 128 [Test]
@@ -136,6 +142,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
136 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); 142 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId);
137 143
138 Assert.That(deletedNpc, Is.Null); 144 Assert.That(deletedNpc, Is.Null);
145 IClientAPI client;
146 Assert.That(m_scene.TryGetClient(npcId, out client), Is.False);
147
148 // Have to account for SP still present.
149 Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
139 } 150 }
140 151
141 [Test] 152 [Test]
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 0551c0b..b5beffc 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -3341,7 +3341,6 @@ Console.WriteLine(" JointCreateFixed");
3341 m_material = pMaterial; 3341 m_material = pMaterial;
3342 } 3342 }
3343 3343
3344
3345 private void CheckMeshAsset() 3344 private void CheckMeshAsset()
3346 { 3345 {
3347 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) 3346 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
@@ -3351,12 +3350,12 @@ Console.WriteLine(" JointCreateFixed");
3351 { 3350 {
3352 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; 3351 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
3353 if (assetProvider != null) 3352 if (assetProvider != null)
3354 assetProvider(_pbs.SculptTexture, MeshAssetReveived); 3353 assetProvider(_pbs.SculptTexture, MeshAssetReceived);
3355 }); 3354 });
3356 } 3355 }
3357 } 3356 }
3358 3357
3359 void MeshAssetReveived(AssetBase asset) 3358 private void MeshAssetReceived(AssetBase asset)
3360 { 3359 {
3361 if (asset.Data != null && asset.Data.Length > 0) 3360 if (asset.Data != null && asset.Data.Length > 0)
3362 { 3361 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 9011966..3bbdbe8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -113,6 +113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
113 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 113 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
114 new Dictionary<UUID, UserInfoCacheEntry>(); 114 new Dictionary<UUID, UserInfoCacheEntry>();
115 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 115 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
116 protected ISoundModule m_SoundModule = null;
116 117
117// protected Timer m_ShoutSayTimer; 118// protected Timer m_ShoutSayTimer;
118 protected int m_SayShoutCount = 0; 119 protected int m_SayShoutCount = 0;
@@ -160,6 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
160 m_TransferModule = 161 m_TransferModule =
161 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 162 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
162 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 163 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
164 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
163 165
164 AsyncCommands = new AsyncCommandManager(ScriptEngine); 166 AsyncCommands = new AsyncCommandManager(ScriptEngine);
165 } 167 }
@@ -427,6 +429,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
427 return key; 429 return key;
428 } 430 }
429 431
432 /// <summary>
433 /// Return the UUID of the asset matching the specified key or name
434 /// and asset type.
435 /// </summary>
436 /// <param name="k"></param>
437 /// <param name="type"></param>
438 /// <returns></returns>
439 protected UUID KeyOrName(string k, AssetType type)
440 {
441 UUID key;
442
443 if (!UUID.TryParse(k, out key))
444 {
445 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
446 if (item != null && item.Type == (int)type)
447 key = item.AssetID;
448 }
449 else
450 {
451 lock (m_host.TaskInventory)
452 {
453 foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory)
454 {
455 if (item.Value.Type == (int)type && item.Value.Name == k)
456 {
457 key = item.Value.ItemID;
458 break;
459 }
460 }
461 }
462 }
463
464
465 return key;
466 }
467
430 //These are the implementations of the various ll-functions used by the LSL scripts. 468 //These are the implementations of the various ll-functions used by the LSL scripts.
431 public LSL_Float llSin(double f) 469 public LSL_Float llSin(double f)
432 { 470 {
@@ -2279,8 +2317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2279 public LSL_Vector llGetPos() 2317 public LSL_Vector llGetPos()
2280 { 2318 {
2281 m_host.AddScriptLPS(1); 2319 m_host.AddScriptLPS(1);
2282 Vector3 pos = m_host.GetWorldPosition(); 2320 return m_host.GetWorldPosition();
2283 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2284 } 2321 }
2285 2322
2286 public LSL_Vector llGetLocalPos() 2323 public LSL_Vector llGetLocalPos()
@@ -2638,63 +2675,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2638 m_host.AddScriptLPS(1); 2675 m_host.AddScriptLPS(1);
2639 2676
2640 // send the sound, once, to all clients in range 2677 // send the sound, once, to all clients in range
2641 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); 2678 if (m_SoundModule != null)
2679 {
2680 m_SoundModule.SendSound(m_host.UUID,
2681 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2682 0, false, false);
2683 }
2642 } 2684 }
2643 2685
2644 // Xantor 20080528 we should do this differently.
2645 // 1) apply the sound to the object
2646 // 2) schedule full update
2647 // just sending the sound out once doesn't work so well when other avatars come in view later on
2648 // or when the prim gets moved, changed, sat on, whatever
2649 // see large number of mantises (mantes?)
2650 // 20080530 Updated to remove code duplication
2651 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
2652 public void llLoopSound(string sound, double volume) 2686 public void llLoopSound(string sound, double volume)
2653 { 2687 {
2654 m_host.AddScriptLPS(1); 2688 m_host.AddScriptLPS(1);
2655 2689 if (m_SoundModule != null)
2656 if (m_host.Sound != UUID.Zero) 2690 {
2657 llStopSound(); 2691 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
2658 2692 volume, 20, false);
2659 m_host.Sound = KeyOrName(sound); 2693 }
2660 m_host.SoundGain = volume;
2661 m_host.SoundFlags = 1; // looping
2662 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2663
2664 m_host.ScheduleFullUpdate();
2665 m_host.SendFullUpdateToAllClients();
2666 } 2694 }
2667 2695
2668 public void llLoopSoundMaster(string sound, double volume) 2696 public void llLoopSoundMaster(string sound, double volume)
2669 { 2697 {
2670 m_host.AddScriptLPS(1); 2698 m_host.AddScriptLPS(1);
2671 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 2699 if (m_SoundModule != null)
2672 lock (m_host.ParentGroup.LoopSoundSlavePrims)
2673 { 2700 {
2674 foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) 2701 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
2675 { 2702 volume, 20, true);
2676 if (prim.Sound != UUID.Zero)
2677 llStopSound();
2678
2679 prim.Sound = KeyOrName(sound);
2680 prim.SoundGain = volume;
2681 prim.SoundFlags = 1; // looping
2682 prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2683
2684 prim.ScheduleFullUpdate();
2685 prim.SendFullUpdateToAllClients();
2686 }
2687 } 2703 }
2688 if (m_host.Sound != UUID.Zero)
2689 llStopSound();
2690
2691 m_host.Sound = KeyOrName(sound);
2692 m_host.SoundGain = volume;
2693 m_host.SoundFlags = 1; // looping
2694 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2695
2696 m_host.ScheduleFullUpdate();
2697 m_host.SendFullUpdateToAllClients();
2698 } 2704 }
2699 2705
2700 public void llLoopSoundSlave(string sound, double volume) 2706 public void llLoopSoundSlave(string sound, double volume)
@@ -2711,61 +2717,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2711 m_host.AddScriptLPS(1); 2717 m_host.AddScriptLPS(1);
2712 2718
2713 // send the sound, once, to all clients in range 2719 // send the sound, once, to all clients in range
2714 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); 2720 if (m_SoundModule != null)
2721 {
2722 m_SoundModule.SendSound(m_host.UUID,
2723 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2724 0, true, false);
2725 }
2715 } 2726 }
2716 2727
2717 public void llTriggerSound(string sound, double volume) 2728 public void llTriggerSound(string sound, double volume)
2718 { 2729 {
2719 m_host.AddScriptLPS(1); 2730 m_host.AddScriptLPS(1);
2720 // send the sound, once, to all clients in range 2731 // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
2721 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); 2732 if (m_SoundModule != null)
2733 {
2734 m_SoundModule.SendSound(m_host.UUID,
2735 KeyOrName(sound, AssetType.Sound), volume, true, 0, 0,
2736 false, false);
2737 }
2722 } 2738 }
2723 2739
2724 // Xantor 20080528: Clear prim data of sound instead
2725 public void llStopSound() 2740 public void llStopSound()
2726 { 2741 {
2727 m_host.AddScriptLPS(1); 2742 m_host.AddScriptLPS(1);
2728 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 2743
2729 { 2744 if (m_SoundModule != null)
2730 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 2745 m_SoundModule.StopSound(m_host.UUID);
2731 {
2732 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
2733 {
2734 part.Sound = UUID.Zero;
2735 part.SoundGain = 0;
2736 part.SoundFlags = 0;
2737 part.SoundRadius = 0;
2738 part.ScheduleFullUpdate();
2739 part.SendFullUpdateToAllClients();
2740 }
2741 m_host.ParentGroup.LoopSoundMasterPrim = null;
2742 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
2743 }
2744 else
2745 {
2746 m_host.Sound = UUID.Zero;
2747 m_host.SoundGain = 0;
2748 m_host.SoundFlags = 0;
2749 m_host.SoundRadius = 0;
2750 m_host.ScheduleFullUpdate();
2751 m_host.SendFullUpdateToAllClients();
2752 }
2753 }
2754 else
2755 {
2756 m_host.Sound = UUID.Zero;
2757 m_host.SoundGain = 0;
2758 m_host.SoundFlags = 0;
2759 m_host.SoundRadius = 0;
2760 m_host.ScheduleFullUpdate();
2761 m_host.SendFullUpdateToAllClients();
2762 }
2763 } 2746 }
2764 2747
2765 public void llPreloadSound(string sound) 2748 public void llPreloadSound(string sound)
2766 { 2749 {
2767 m_host.AddScriptLPS(1); 2750 m_host.AddScriptLPS(1);
2768 m_host.PreloadSound(sound); 2751 if (m_SoundModule != null)
2752 m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0);
2769 ScriptSleep(1000); 2753 ScriptSleep(1000);
2770 } 2754 }
2771 2755
@@ -4747,16 +4731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4747 return; 4731 return;
4748 } 4732 }
4749 // TODO: Parameter check logic required. 4733 // TODO: Parameter check logic required.
4750 UUID soundId = UUID.Zero; 4734 m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound);
4751 if (!UUID.TryParse(impact_sound, out soundId))
4752 {
4753 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound);
4754
4755 if (item != null && item.Type == (int)AssetType.Sound)
4756 soundId = item.AssetID;
4757 }
4758
4759 m_host.CollisionSound = soundId;
4760 m_host.CollisionSoundVolume = (float)impact_volume; 4735 m_host.CollisionSoundVolume = (float)impact_volume;
4761 m_host.CollisionSoundType = 1; 4736 m_host.CollisionSoundType = 1;
4762 } 4737 }
@@ -6318,10 +6293,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6318 LSL_Vector bottom_south_west) 6293 LSL_Vector bottom_south_west)
6319 { 6294 {
6320 m_host.AddScriptLPS(1); 6295 m_host.AddScriptLPS(1);
6321 float radius1 = (float)llVecDist(llGetPos(), top_north_east); 6296 if (m_SoundModule != null)
6322 float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); 6297 {
6323 float radius = Math.Abs(radius1 - radius2); 6298 m_SoundModule.TriggerSoundLimited(m_host.UUID,
6324 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); 6299 KeyOrName(sound, AssetType.Sound), volume,
6300 bottom_south_west, top_north_east);
6301 }
6325 } 6302 }
6326 6303
6327 public void llEjectFromLand(string pest) 6304 public void llEjectFromLand(string pest)
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index efcca70..ae5e788 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -1683,5 +1683,12 @@ Enabled = False
1683 ;; default is module is disabled at the top level 1683 ;; default is module is disabled at the top level
1684 AutoBackupModuleEnabled = false 1684 AutoBackupModuleEnabled = false
1685 1685
1686[Sounds]
1687 ;; {Module} {} {Implementation of ISoundModule to use.} {OpenSim.Region.CoreModules.dll:SoundModule}
1688 Module = OpenSim.Region.CoreModules.dll:SoundModule
1689
1690 ;; {MaxDistance} {} {Cut-off distance at which sounds will not be sent to users} {100.0}
1691 MaxDistance = 100.0
1692
1686[Modules] 1693[Modules]
1687 Include-modules = "addon-modules/*/config/*.ini" 1694 Include-modules = "addon-modules/*/config/*.ini"