aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Scripting
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs61
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs315
-rw-r--r--OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs110
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs34
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs22
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs87
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs383
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs281
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs213
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs375
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs82
11 files changed, 1616 insertions, 347 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
new file mode 100644
index 0000000..fce9490
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27
28using System;
29using System.Drawing;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
33{
34 public class DynamicTexture : IDynamicTexture
35 {
36 public string InputCommands { get; private set; }
37 public Uri InputUri { get; private set; }
38 public string InputParams { get; private set; }
39 public byte[] Data { get; private set; }
40 public Size Size { get; private set; }
41 public bool IsReuseable { get; private set; }
42
43 public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
44 {
45 InputCommands = inputCommands;
46 InputParams = inputParams;
47 Data = data;
48 Size = size;
49 IsReuseable = isReuseable;
50 }
51
52 public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
53 {
54 InputUri = inputUri;
55 InputParams = inputParams;
56 Data = data;
57 Size = size;
58 IsReuseable = isReuseable;
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 18bd018..9d77b19 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -37,18 +37,36 @@ using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using log4net; 38using log4net;
39using System.Reflection; 39using System.Reflection;
40using Mono.Addins;
40 41
41namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture 42namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 43{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicTextureModule")]
45 public class DynamicTextureModule : ISharedRegionModule, IDynamicTextureManager
44 { 46 {
45 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 48
47 private const int ALL_SIDES = -1; 49 private const int ALL_SIDES = -1;
48 50
49 public const int DISP_EXPIRE = 1; 51 public const int DISP_EXPIRE = 1;
50 public const int DISP_TEMP = 2; 52 public const int DISP_TEMP = 2;
51 53
54 /// <summary>
55 /// If true then where possible dynamic textures are reused.
56 /// </summary>
57 public bool ReuseTextures { get; set; }
58
59 /// <summary>
60 /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
61 /// </summary>
62 /// <remarks>
63 /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
64 /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
65 /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
66 /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
67 /// to work around this problem.</remarks>
68 public bool ReuseLowDataTextures { get; set; }
69
52 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 70 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
53 71
54 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 72 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -56,6 +74,25 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
56 74
57 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); 75 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
58 76
77 /// <summary>
78 /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
79 /// regenerate.
80 /// </summary>
81 /// <remarks>
82 /// Key is string.Format("{0}{1}", data
83 /// </remarks>
84 private Cache m_reuseableDynamicTextures;
85
86 /// <summary>
87 /// This constructor is only here because of the Unit Tests...
88 /// Don't use it.
89 /// </summary>
90 public DynamicTextureModule()
91 {
92 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
93 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
94 }
95
59 #region IDynamicTextureManager Members 96 #region IDynamicTextureManager Members
60 97
61 public void RegisterRender(string handleType, IDynamicTextureRender render) 98 public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -69,17 +106,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
69 /// <summary> 106 /// <summary>
70 /// Called by code which actually renders the dynamic texture to supply texture data. 107 /// Called by code which actually renders the dynamic texture to supply texture data.
71 /// </summary> 108 /// </summary>
72 /// <param name="id"></param> 109 /// <param name="updaterId"></param>
73 /// <param name="data"></param> 110 /// <param name="texture"></param>
74 public void ReturnData(UUID id, byte[] data) 111 public void ReturnData(UUID updaterId, IDynamicTexture texture)
75 { 112 {
76 DynamicTextureUpdater updater = null; 113 DynamicTextureUpdater updater = null;
77 114
78 lock (Updaters) 115 lock (Updaters)
79 { 116 {
80 if (Updaters.ContainsKey(id)) 117 if (Updaters.ContainsKey(updaterId))
81 { 118 {
82 updater = Updaters[id]; 119 updater = Updaters[updaterId];
83 } 120 }
84 } 121 }
85 122
@@ -88,7 +125,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
88 if (RegisteredScenes.ContainsKey(updater.SimUUID)) 125 if (RegisteredScenes.ContainsKey(updater.SimUUID))
89 { 126 {
90 Scene scene = RegisteredScenes[updater.SimUUID]; 127 Scene scene = RegisteredScenes[updater.SimUUID];
91 updater.DataReceived(data, scene); 128 UUID newTextureID = updater.DataReceived(texture.Data, scene);
129
130 if (ReuseTextures
131 && !updater.BlendWithOldTexture
132 && texture.IsReuseable
133 && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
134 {
135 m_reuseableDynamicTextures.Store(
136 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
137 }
92 } 138 }
93 } 139 }
94 140
@@ -104,6 +150,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
104 } 150 }
105 } 151 }
106 152
153 /// <summary>
154 /// Determines whether the texture is reuseable based on its data size.
155 /// </summary>
156 /// <remarks>
157 /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
158 /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
159 /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
160 /// </remarks>
161 /// <returns></returns>
162 private bool IsDataSizeReuseable(IDynamicTexture texture)
163 {
164// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
165 int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
166
167// m_log.DebugFormat(
168// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
169// discardLevel2DataThreshold, texture.Data.Length);
170
171 return discardLevel2DataThreshold < texture.Data.Length;
172 }
173
107 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 174 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
108 string extraParams, int updateTimer) 175 string extraParams, int updateTimer)
109 { 176 {
@@ -167,22 +234,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
167 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 234 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
168 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) 235 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
169 { 236 {
170 if (RenderPlugins.ContainsKey(contentType)) 237 if (!RenderPlugins.ContainsKey(contentType))
238 return UUID.Zero;
239
240 Scene scene;
241 RegisteredScenes.TryGetValue(simID, out scene);
242
243 if (scene == null)
244 return UUID.Zero;
245
246 SceneObjectPart part = scene.GetSceneObjectPart(primID);
247
248 if (part == null)
249 return UUID.Zero;
250
251 // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
252 // them.
253 if (ReuseTextures)
254 disp = disp & ~DISP_EXPIRE;
255
256 DynamicTextureUpdater updater = new DynamicTextureUpdater();
257 updater.SimUUID = simID;
258 updater.PrimID = primID;
259 updater.ContentType = contentType;
260 updater.BodyData = data;
261 updater.UpdateTimer = updateTimer;
262 updater.UpdaterID = UUID.Random();
263 updater.Params = extraParams;
264 updater.BlendWithOldTexture = SetBlending;
265 updater.FrontAlpha = AlphaValue;
266 updater.Face = face;
267 updater.Url = "Local image";
268 updater.Disp = disp;
269
270 object objReusableTextureUUID = null;
271
272 if (ReuseTextures && !updater.BlendWithOldTexture)
171 { 273 {
172 DynamicTextureUpdater updater = new DynamicTextureUpdater(); 274 string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams);
173 updater.SimUUID = simID; 275 objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey);
174 updater.PrimID = primID;
175 updater.ContentType = contentType;
176 updater.BodyData = data;
177 updater.UpdateTimer = updateTimer;
178 updater.UpdaterID = UUID.Random();
179 updater.Params = extraParams;
180 updater.BlendWithOldTexture = SetBlending;
181 updater.FrontAlpha = AlphaValue;
182 updater.Face = face;
183 updater.Url = "Local image";
184 updater.Disp = disp;
185 276
277 if (objReusableTextureUUID != null)
278 {
279 // If something else has removed this temporary asset from the cache, detect and invalidate
280 // our cached uuid.
281 if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null)
282 {
283 m_reuseableDynamicTextures.Invalidate(reuseableTextureKey);
284 objReusableTextureUUID = null;
285 }
286 }
287 }
288
289 // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
290 if (objReusableTextureUUID == null)
291 {
186 lock (Updaters) 292 lock (Updaters)
187 { 293 {
188 if (!Updaters.ContainsKey(updater.UpdaterID)) 294 if (!Updaters.ContainsKey(updater.UpdaterID))
@@ -191,11 +297,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
191 } 297 }
192 } 298 }
193 299
300// m_log.DebugFormat(
301// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
302// part.Name, part.ParentGroup.Scene.Name);
303
194 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); 304 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
195 return updater.UpdaterID;
196 } 305 }
197 306 else
198 return UUID.Zero; 307 {
308// m_log.DebugFormat(
309// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
310// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
311
312 // No need to add to updaters as the texture is always the same. Not that this functionality
313 // apppears to be implemented anyway.
314 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
315 }
316
317 return updater.UpdaterID;
318 }
319
320 private string GenerateReusableTextureKey(string data, string extraParams)
321 {
322 return string.Format("{0}{1}", data, extraParams);
199 } 323 }
200 324
201 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 325 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
@@ -211,9 +335,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
211 335
212 #endregion 336 #endregion
213 337
214 #region IRegionModule Members 338 #region ISharedRegionModule Members
215 339
216 public void Initialise(Scene scene, IConfigSource config) 340 public void Initialise(IConfigSource config)
341 {
342 IConfig texturesConfig = config.Configs["Textures"];
343 if (texturesConfig != null)
344 {
345 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
346 ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
347
348 if (ReuseTextures)
349 {
350 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
351 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
352 }
353 }
354 }
355
356 public void PostInitialise()
357 {
358 }
359
360 public void AddRegion(Scene scene)
217 { 361 {
218 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) 362 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
219 { 363 {
@@ -222,8 +366,14 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
222 } 366 }
223 } 367 }
224 368
225 public void PostInitialise() 369 public void RegionLoaded(Scene scene)
370 {
371 }
372
373 public void RemoveRegion(Scene scene)
226 { 374 {
375 if (RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
376 RegisteredScenes.Remove(scene.RegionInfo.RegionID);
227 } 377 }
228 378
229 public void Close() 379 public void Close()
@@ -235,9 +385,9 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
235 get { return "DynamicTextureModule"; } 385 get { return "DynamicTextureModule"; }
236 } 386 }
237 387
238 public bool IsSharedModule 388 public Type ReplaceableInterface
239 { 389 {
240 get { return true; } 390 get { return null; }
241 } 391 }
242 392
243 #endregion 393 #endregion
@@ -269,9 +419,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
269 } 419 }
270 420
271 /// <summary> 421 /// <summary>
422 /// Update the given part with the new texture.
423 /// </summary>
424 /// <returns>
425 /// The old texture UUID.
426 /// </returns>
427 public UUID UpdatePart(SceneObjectPart part, UUID textureID)
428 {
429 UUID oldID;
430
431 lock (part)
432 {
433 // mostly keep the values from before
434 Primitive.TextureEntry tmptex = part.Shape.Textures;
435
436 // FIXME: Need to return the appropriate ID if only a single face is replaced.
437 oldID = tmptex.DefaultTexture.TextureID;
438
439 if (Face == ALL_SIDES)
440 {
441 oldID = tmptex.DefaultTexture.TextureID;
442 tmptex.DefaultTexture.TextureID = textureID;
443 }
444 else
445 {
446 try
447 {
448 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
449 texface.TextureID = textureID;
450 tmptex.FaceTextures[Face] = texface;
451 }
452 catch (Exception)
453 {
454 tmptex.DefaultTexture.TextureID = textureID;
455 }
456 }
457
458 // I'm pretty sure we always want to force this to true
459 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
460 // tmptex.DefaultTexture.Fullbright = true;
461
462 part.UpdateTextureEntry(tmptex.GetBytes());
463 }
464
465 return oldID;
466 }
467
468 /// <summary>
272 /// Called once new texture data has been received for this updater. 469 /// Called once new texture data has been received for this updater.
273 /// </summary> 470 /// </summary>
274 public void DataReceived(byte[] data, Scene scene) 471 /// <param name="data"></param>
472 /// <param name="scene"></param>
473 /// <param name="isReuseable">True if the data given is reuseable.</param>
474 /// <returns>The asset UUID given to the incoming data.</returns>
475 public UUID DataReceived(byte[] data, Scene scene)
275 { 476 {
276 SceneObjectPart part = scene.GetSceneObjectPart(PrimID); 477 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
277 478
@@ -281,7 +482,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
281 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 482 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
282 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 483 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
283 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 484 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
284 return; 485
486 return UUID.Zero;
285 } 487 }
286 488
287 byte[] assetData = null; 489 byte[] assetData = null;
@@ -319,56 +521,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
319 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 521 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
320 if (cacheLayerDecode != null) 522 if (cacheLayerDecode != null)
321 { 523 {
322 cacheLayerDecode.Decode(asset.FullID, asset.Data); 524 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
323 cacheLayerDecode = null; 525 m_log.WarnFormat(
526 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
527 asset.ID, part.Name, part.ParentGroup.Scene.Name);
324 } 528 }
325 529
326 UUID oldID = UUID.Zero; 530 UUID oldID = UpdatePart(part, asset.FullID);
327
328 lock (part)
329 {
330 // mostly keep the values from before
331 Primitive.TextureEntry tmptex = part.Shape.Textures;
332
333 // remove the old asset from the cache
334 oldID = tmptex.DefaultTexture.TextureID;
335
336 if (Face == ALL_SIDES)
337 {
338 tmptex.DefaultTexture.TextureID = asset.FullID;
339 }
340 else
341 {
342 try
343 {
344 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
345 texface.TextureID = asset.FullID;
346 tmptex.FaceTextures[Face] = texface;
347 }
348 catch (Exception)
349 {
350 tmptex.DefaultTexture.TextureID = asset.FullID;
351 }
352 }
353
354 // I'm pretty sure we always want to force this to true
355 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
356 // tmptex.DefaultTexture.Fullbright = true;
357
358 part.UpdateTextureEntry(tmptex.GetBytes());
359 }
360 531
361 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) 532 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
362 { 533 {
363 if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); 534 if (oldAsset == null)
535 oldAsset = scene.AssetService.Get(oldID.ToString());
536
364 if (oldAsset != null) 537 if (oldAsset != null)
365 { 538 {
366 if (oldAsset.Temporary == true) 539 if (oldAsset.Temporary)
367 { 540 {
368 scene.AssetService.Delete(oldID.ToString()); 541 scene.AssetService.Delete(oldID.ToString());
369 } 542 }
370 } 543 }
371 } 544 }
545
546 return asset.FullID;
372 } 547 }
373 548
374 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 549 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
index e91e8b9..d943b20 100644
--- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
@@ -37,10 +37,12 @@ using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using Mono.Addins;
40 41
41namespace OpenSim.Region.CoreModules.Scripting.EmailModules 42namespace OpenSim.Region.CoreModules.Scripting.EmailModules
42{ 43{
43 public class EmailModule : IRegionModule, IEmailModule 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EmailModule")]
45 public class EmailModule : ISharedRegionModule, IEmailModule
44 { 46 {
45 // 47 //
46 // Log 48 // Log
@@ -72,31 +74,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
72 74
73 private bool m_Enabled = false; 75 private bool m_Enabled = false;
74 76
75 public void InsertEmail(UUID to, Email email) 77 #region ISharedRegionModule
76 {
77 // It's tempting to create the queue here. Don't; objects which have
78 // not yet called GetNextEmail should have no queue, and emails to them
79 // should be silently dropped.
80
81 lock (m_MailQueues)
82 {
83 if (m_MailQueues.ContainsKey(to))
84 {
85 if (m_MailQueues[to].Count >= m_MaxQueueSize)
86 {
87 // fail silently
88 return;
89 }
90
91 lock (m_MailQueues[to])
92 {
93 m_MailQueues[to].Add(email);
94 }
95 }
96 }
97 }
98 78
99 public void Initialise(Scene scene, IConfigSource config) 79 public void Initialise(IConfigSource config)
100 { 80 {
101 m_Config = config; 81 m_Config = config;
102 IConfig SMTPConfig; 82 IConfig SMTPConfig;
@@ -129,36 +109,44 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
129 SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT); 109 SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT);
130 SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN); 110 SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN);
131 SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD); 111 SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD);
132 m_MaxEmailSize = SMTPConfig.GetInt("email_max_size", m_MaxEmailSize); 112 m_MaxEmailSize = SMTPConfig.GetInt("email_max_size", m_MaxEmailSize);
133 } 113 }
134 catch (Exception e) 114 catch (Exception e)
135 { 115 {
136 m_log.Error("[EMAIL] DefaultEmailModule not configured: "+ e.Message); 116 m_log.Error("[EMAIL] DefaultEmailModule not configured: " + e.Message);
137 m_Enabled = false; 117 m_Enabled = false;
138 return; 118 return;
139 } 119 }
140 120
141 // It's a go! 121 }
142 if (m_Enabled) 122
123 public void AddRegion(Scene scene)
124 {
125 if (!m_Enabled)
126 return;
127
128 // It's a go!
129 lock (m_Scenes)
143 { 130 {
144 lock (m_Scenes) 131 // Claim the interface slot
145 { 132 scene.RegisterModuleInterface<IEmailModule>(this);
146 // Claim the interface slot
147 scene.RegisterModuleInterface<IEmailModule>(this);
148 133
149 // Add to scene list 134 // Add to scene list
150 if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle)) 135 if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle))
151 { 136 {
152 m_Scenes[scene.RegionInfo.RegionHandle] = scene; 137 m_Scenes[scene.RegionInfo.RegionHandle] = scene;
153 } 138 }
154 else 139 else
155 { 140 {
156 m_Scenes.Add(scene.RegionInfo.RegionHandle, scene); 141 m_Scenes.Add(scene.RegionInfo.RegionHandle, scene);
157 }
158 } 142 }
159
160 m_log.Info("[EMAIL] Activated DefaultEmailModule");
161 } 143 }
144
145 m_log.Info("[EMAIL] Activated DefaultEmailModule");
146 }
147
148 public void RemoveRegion(Scene scene)
149 {
162 } 150 }
163 151
164 public void PostInitialise() 152 public void PostInitialise()
@@ -174,9 +162,39 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
174 get { return "DefaultEmailModule"; } 162 get { return "DefaultEmailModule"; }
175 } 163 }
176 164
177 public bool IsSharedModule 165 public Type ReplaceableInterface
166 {
167 get { return null; }
168 }
169
170 public void RegionLoaded(Scene scene)
178 { 171 {
179 get { return true; } 172 }
173
174 #endregion
175
176 public void InsertEmail(UUID to, Email email)
177 {
178 // It's tempting to create the queue here. Don't; objects which have
179 // not yet called GetNextEmail should have no queue, and emails to them
180 // should be silently dropped.
181
182 lock (m_MailQueues)
183 {
184 if (m_MailQueues.ContainsKey(to))
185 {
186 if (m_MailQueues[to].Count >= m_MaxQueueSize)
187 {
188 // fail silently
189 return;
190 }
191
192 lock (m_MailQueues[to])
193 {
194 m_MailQueues[to].Add(email);
195 }
196 }
197 }
180 } 198 }
181 199
182 private bool IsLocal(UUID objectID) 200 private bool IsLocal(UUID objectID)
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 9dac6b9..a0ae203 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -41,6 +41,7 @@ using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using Mono.Addins;
44 45
45/***************************************************** 46/*****************************************************
46 * 47 *
@@ -87,7 +88,8 @@ using OpenSim.Region.Framework.Scenes;
87 88
88namespace OpenSim.Region.CoreModules.Scripting.HttpRequest 89namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
89{ 90{
90 public class HttpRequestModule : IRegionModule, IHttpRequestModule 91 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HttpRequestModule")]
92 public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule
91 { 93 {
92 private object HttpListLock = new object(); 94 private object HttpListLock = new object();
93 private int httpTimeout = 30000; 95 private int httpTimeout = 30000;
@@ -270,24 +272,38 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
270 272
271 #endregion 273 #endregion
272 274
273 #region IRegionModule Members 275 #region ISharedRegionModule Members
274 276
275 public void Initialise(Scene scene, IConfigSource config) 277 public void Initialise(IConfigSource config)
276 { 278 {
277 m_scene = scene;
278
279 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
280
281 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 279 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
282 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 280 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
283 281
284 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 282 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
285 } 283 }
286 284
285 public void AddRegion(Scene scene)
286 {
287 m_scene = scene;
288
289 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
290 }
291
292 public void RemoveRegion(Scene scene)
293 {
294 scene.UnregisterModuleInterface<IHttpRequestModule>(this);
295 if (scene == m_scene)
296 m_scene = null;
297 }
298
287 public void PostInitialise() 299 public void PostInitialise()
288 { 300 {
289 } 301 }
290 302
303 public void RegionLoaded(Scene scene)
304 {
305 }
306
291 public void Close() 307 public void Close()
292 { 308 {
293 } 309 }
@@ -297,9 +313,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
297 get { return m_name; } 313 get { return m_name; }
298 } 314 }
299 315
300 public bool IsSharedModule 316 public Type ReplaceableInterface
301 { 317 {
302 get { return true; } 318 get { return null; }
303 } 319 }
304 320
305 #endregion 321 #endregion
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 56221aa..da59eab 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Collections; 31using System.Collections;
32using System.Reflection; 32using System.Reflection;
33using log4net; 33using log4net;
34using Mono.Addins;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenSim.Framework; 37using OpenSim.Framework;
@@ -58,6 +59,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
58 public string body; 59 public string body;
59 public int responseCode; 60 public int responseCode;
60 public string responseBody; 61 public string responseBody;
62 public string responseType = "text/plain";
61 //public ManualResetEvent ev; 63 //public ManualResetEvent ev;
62 public bool requestDone; 64 public bool requestDone;
63 public int startTime; 65 public int startTime;
@@ -65,6 +67,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
65 public string uri; 67 public string uri;
66 } 68 }
67 69
70 /// <summary>
71 /// This module provides external URLs for in-world scripts.
72 /// </summary>
73 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UrlModule")]
68 public class UrlModule : ISharedRegionModule, IUrlModule 74 public class UrlModule : ISharedRegionModule, IUrlModule
69 { 75 {
70 private static readonly ILog m_log = 76 private static readonly ILog m_log =
@@ -270,6 +276,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
270 } 276 }
271 } 277 }
272 278
279 public void HttpContentType(UUID request, string type)
280 {
281 lock (m_UrlMap)
282 {
283 if (m_RequestMap.ContainsKey(request))
284 {
285 UrlData urlData = m_RequestMap[request];
286 urlData.requests[request].responseType = type;
287 }
288 else
289 {
290 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
291 }
292 }
293 }
294
273 public void HttpResponse(UUID request, int status, string body) 295 public void HttpResponse(UUID request, int status, string body)
274 { 296 {
275 lock (m_RequestMap) 297 lock (m_RequestMap)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 6f83948..65737fa 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,14 +32,17 @@ using System.Net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Imaging; 34using OpenMetaverse.Imaging;
35using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using log4net; 38using log4net;
38using System.Reflection; 39using System.Reflection;
40using Mono.Addins;
39 41
40namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL 42namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
41{ 43{
42 public class LoadImageURLModule : IRegionModule, IDynamicTextureRender 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LoadImageURLModule")]
45 public class LoadImageURLModule : ISharedRegionModule, IDynamicTextureRender
43 { 46 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 48
@@ -67,12 +70,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
67 return true; 70 return true;
68 } 71 }
69 72
70 public byte[] ConvertUrl(string url, string extraParams) 73// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
74// {
75// // We don't support conversion of body data.
76// return false;
77// }
78
79 public IDynamicTexture ConvertUrl(string url, string extraParams)
71 { 80 {
72 return null; 81 return null;
73 } 82 }
74 83
75 public byte[] ConvertStream(Stream data, string extraParams) 84 public IDynamicTexture ConvertData(string bodyData, string extraParams)
76 { 85 {
77 return null; 86 return null;
78 } 87 }
@@ -97,22 +106,32 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
97 106
98 #endregion 107 #endregion
99 108
100 #region IRegionModule Members 109 #region ISharedRegionModule Members
101 110
102 public void Initialise(Scene scene, IConfigSource config) 111 public void Initialise(IConfigSource config)
103 { 112 {
104 if (m_scene == null)
105 {
106 m_scene = scene;
107 }
108
109 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 113 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
110 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 114 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
111 } 115 }
112 116
113 public void PostInitialise() 117 public void PostInitialise()
114 { 118 {
115 if (m_scene != null) 119 }
120
121 public void AddRegion(Scene scene)
122 {
123 if (m_scene == null)
124 m_scene = scene;
125
126 }
127
128 public void RemoveRegion(Scene scene)
129 {
130 }
131
132 public void RegionLoaded(Scene scene)
133 {
134 if (m_textureManager == null && m_scene == scene)
116 { 135 {
117 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>(); 136 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
118 if (m_textureManager != null) 137 if (m_textureManager != null)
@@ -131,9 +150,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
131 get { return m_name; } 150 get { return m_name; }
132 } 151 }
133 152
134 public bool IsSharedModule 153 public Type ReplaceableInterface
135 { 154 {
136 get { return true; } 155 get { return null; }
137 } 156 }
138 157
139 #endregion 158 #endregion
@@ -165,11 +184,17 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
165 184
166 private void HttpRequestReturn(IAsyncResult result) 185 private void HttpRequestReturn(IAsyncResult result)
167 { 186 {
187 if (m_textureManager == null)
188 {
189 m_log.WarnFormat("[LOADIMAGEURLMODULE]: No texture manager. Can't function.");
190 return;
191 }
168 192
169 RequestState state = (RequestState) result.AsyncState; 193 RequestState state = (RequestState) result.AsyncState;
170 WebRequest request = (WebRequest) state.Request; 194 WebRequest request = (WebRequest) state.Request;
171 Stream stream = null; 195 Stream stream = null;
172 byte[] imageJ2000 = new byte[0]; 196 byte[] imageJ2000 = new byte[0];
197 Size newSize = new Size(0, 0);
173 198
174 try 199 try
175 { 200 {
@@ -182,37 +207,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
182 try 207 try
183 { 208 {
184 Bitmap image = new Bitmap(stream); 209 Bitmap image = new Bitmap(stream);
185 Size newsize;
186 210
187 // TODO: make this a bit less hard coded 211 // TODO: make this a bit less hard coded
188 if ((image.Height < 64) && (image.Width < 64)) 212 if ((image.Height < 64) && (image.Width < 64))
189 { 213 {
190 newsize = new Size(32, 32); 214 newSize.Width = 32;
215 newSize.Height = 32;
191 } 216 }
192 else if ((image.Height < 128) && (image.Width < 128)) 217 else if ((image.Height < 128) && (image.Width < 128))
193 { 218 {
194 newsize = new Size(64, 64); 219 newSize.Width = 64;
220 newSize.Height = 64;
195 } 221 }
196 else if ((image.Height < 256) && (image.Width < 256)) 222 else if ((image.Height < 256) && (image.Width < 256))
197 { 223 {
198 newsize = new Size(128, 128); 224 newSize.Width = 128;
225 newSize.Height = 128;
199 } 226 }
200 else if ((image.Height < 512 && image.Width < 512)) 227 else if ((image.Height < 512 && image.Width < 512))
201 { 228 {
202 newsize = new Size(256, 256); 229 newSize.Width = 256;
230 newSize.Height = 256;
203 } 231 }
204 else if ((image.Height < 1024 && image.Width < 1024)) 232 else if ((image.Height < 1024 && image.Width < 1024))
205 { 233 {
206 newsize = new Size(512, 512); 234 newSize.Width = 512;
235 newSize.Height = 512;
207 } 236 }
208 else 237 else
209 { 238 {
210 newsize = new Size(1024, 1024); 239 newSize.Width = 1024;
240 newSize.Height = 1024;
211 } 241 }
212 242
213 Bitmap resize = new Bitmap(image, newsize); 243 using (Bitmap resize = new Bitmap(image, newSize))
214 244 {
215 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 245 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
246 }
216 } 247 }
217 catch (Exception) 248 catch (Exception)
218 { 249 {
@@ -227,7 +258,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
227 } 258 }
228 catch (WebException) 259 catch (WebException)
229 { 260 {
230
231 } 261 }
232 finally 262 finally
233 { 263 {
@@ -236,9 +266,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
236 stream.Close(); 266 stream.Close();
237 } 267 }
238 } 268 }
239 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", 269
270 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
240 imageJ2000.Length, state.RequestID); 271 imageJ2000.Length, state.RequestID);
241 m_textureManager.ReturnData(state.RequestID, imageJ2000); 272
273 m_textureManager.ReturnData(
274 state.RequestID,
275 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
276 request.RequestUri, null, imageJ2000, newSize, false));
242 } 277 }
243 278
244 #region Nested type: RequestState 279 #region Nested type: RequestState
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
new file mode 100644
index 0000000..f6e1d39
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -0,0 +1,383 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27
28using System;
29using System.Reflection;
30using System.Collections.Generic;
31using Nini.Config;
32using log4net;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using Mono.Addins;
37using OpenMetaverse;
38using System.Linq;
39using System.Linq.Expressions;
40
41namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private Dictionary<string,object> m_constants = new Dictionary<string,object>();
50
51#region ScriptInvocation
52 protected class ScriptInvocationData
53 {
54 public Delegate ScriptInvocationDelegate { get; private set; }
55 public string FunctionName { get; private set; }
56 public Type[] TypeSignature { get; private set; }
57 public Type ReturnType { get; private set; }
58
59 public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig)
60 {
61 FunctionName = fname;
62 ScriptInvocationDelegate = fn;
63 TypeSignature = callsig;
64 ReturnType = returnsig;
65 }
66 }
67
68 private Dictionary<string,ScriptInvocationData> m_scriptInvocation = new Dictionary<string,ScriptInvocationData>();
69#endregion
70
71 private IScriptModule m_scriptModule = null;
72 public event ScriptCommand OnScriptCommand;
73
74#region RegionModuleInterface
75 public void Initialise(IConfigSource config)
76 {
77 }
78
79 public void AddRegion(Scene scene)
80 {
81 scene.RegisterModuleInterface<IScriptModuleComms>(this);
82 }
83
84 public void RemoveRegion(Scene scene)
85 {
86 }
87
88 public void RegionLoaded(Scene scene)
89 {
90 m_scriptModule = scene.RequestModuleInterface<IScriptModule>();
91
92 if (m_scriptModule != null)
93 m_log.Info("[MODULE COMMANDS]: Script engine found, module active");
94 }
95
96 public string Name
97 {
98 get { return "ScriptModuleCommsModule"; }
99 }
100
101 public Type ReplaceableInterface
102 {
103 get { return null; }
104 }
105
106 public void Close()
107 {
108 }
109#endregion
110
111#region ScriptModuleComms
112
113 public void RaiseEvent(UUID script, string id, string module, string command, string k)
114 {
115 ScriptCommand c = OnScriptCommand;
116
117 if (c == null)
118 return;
119
120 c(script, id, module, command, k);
121 }
122
123 public void DispatchReply(UUID script, int code, string text, string k)
124 {
125 if (m_scriptModule == null)
126 return;
127
128 Object[] args = new Object[] {-1, code, text, k};
129
130 m_scriptModule.PostScriptEvent(script, "link_message", args);
131 }
132
133 private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
134 {
135 BindingFlags getMethodFlags =
136 BindingFlags.NonPublic | BindingFlags.Public;
137
138 if (searchInstanceMethods)
139 getMethodFlags |= BindingFlags.Instance;
140 else
141 getMethodFlags |= BindingFlags.Static;
142
143 return target.GetMethod(meth, getMethodFlags);
144 }
145
146 public void RegisterScriptInvocation(object target, string meth)
147 {
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
149 if (mi == null)
150 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
152 return;
153 }
154
155 RegisterScriptInvocation(target, mi);
156 }
157
158 public void RegisterScriptInvocation(object target, string[] meth)
159 {
160 foreach (string m in meth)
161 RegisterScriptInvocation(target, m);
162 }
163
164 public void RegisterScriptInvocation(object target, MethodInfo mi)
165 {
166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
167
168 Type delegateType;
169 List<Type> typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType)
171 .ToList();
172
173 if (mi.ReturnType == typeof(void))
174 {
175 delegateType = Expression.GetActionType(typeArgs.ToArray());
176 }
177 else
178 {
179 typeArgs.Add(mi.ReturnType);
180 delegateType = Expression.GetFuncType(typeArgs.ToArray());
181 }
182
183 Delegate fcall;
184 if (!(target is Type))
185 fcall = Delegate.CreateDelegate(delegateType, target, mi);
186 else
187 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
188
189 lock (m_scriptInvocation)
190 {
191 ParameterInfo[] parameters = fcall.Method.GetParameters();
192 if (parameters.Length < 2) // Must have two UUID params
193 return;
194
195 // Hide the first two parameters
196 Type[] parmTypes = new Type[parameters.Length - 2];
197 for (int i = 2; i < parameters.Length; i++)
198 parmTypes[i - 2] = parameters[i].ParameterType;
199 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
200 }
201 }
202
203 public void RegisterScriptInvocation(Type target, string[] methods)
204 {
205 foreach (string method in methods)
206 {
207 MethodInfo mi = GetMethodInfoFromType(target, method, false);
208 if (mi == null)
209 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
210 else
211 RegisterScriptInvocation(target, mi);
212 }
213 }
214
215 public void RegisterScriptInvocations(IRegionModuleBase target)
216 {
217 foreach(MethodInfo method in target.GetType().GetMethods(
218 BindingFlags.Public | BindingFlags.Instance |
219 BindingFlags.Static))
220 {
221 if(method.GetCustomAttributes(
222 typeof(ScriptInvocationAttribute), true).Any())
223 {
224 if(method.IsStatic)
225 RegisterScriptInvocation(target.GetType(), method);
226 else
227 RegisterScriptInvocation(target, method);
228 }
229 }
230 }
231
232 public Delegate[] GetScriptInvocationList()
233 {
234 List<Delegate> ret = new List<Delegate>();
235
236 lock (m_scriptInvocation)
237 {
238 foreach (ScriptInvocationData d in m_scriptInvocation.Values)
239 ret.Add(d.ScriptInvocationDelegate);
240 }
241 return ret.ToArray();
242 }
243
244 public string LookupModInvocation(string fname)
245 {
246 lock (m_scriptInvocation)
247 {
248 ScriptInvocationData sid;
249 if (m_scriptInvocation.TryGetValue(fname,out sid))
250 {
251 if (sid.ReturnType == typeof(string))
252 return "modInvokeS";
253 else if (sid.ReturnType == typeof(int))
254 return "modInvokeI";
255 else if (sid.ReturnType == typeof(float))
256 return "modInvokeF";
257 else if (sid.ReturnType == typeof(UUID))
258 return "modInvokeK";
259 else if (sid.ReturnType == typeof(OpenMetaverse.Vector3))
260 return "modInvokeV";
261 else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion))
262 return "modInvokeR";
263 else if (sid.ReturnType == typeof(object[]))
264 return "modInvokeL";
265
266 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
267 }
268 }
269
270 return null;
271 }
272
273 public Delegate LookupScriptInvocation(string fname)
274 {
275 lock (m_scriptInvocation)
276 {
277 ScriptInvocationData sid;
278 if (m_scriptInvocation.TryGetValue(fname,out sid))
279 return sid.ScriptInvocationDelegate;
280 }
281
282 return null;
283 }
284
285 public Type[] LookupTypeSignature(string fname)
286 {
287 lock (m_scriptInvocation)
288 {
289 ScriptInvocationData sid;
290 if (m_scriptInvocation.TryGetValue(fname,out sid))
291 return sid.TypeSignature;
292 }
293
294 return null;
295 }
296
297 public Type LookupReturnType(string fname)
298 {
299 lock (m_scriptInvocation)
300 {
301 ScriptInvocationData sid;
302 if (m_scriptInvocation.TryGetValue(fname,out sid))
303 return sid.ReturnType;
304 }
305
306 return null;
307 }
308
309 public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms)
310 {
311 List<object> olist = new List<object>();
312 olist.Add(hostid);
313 olist.Add(scriptid);
314 foreach (object o in parms)
315 olist.Add(o);
316 Delegate fn = LookupScriptInvocation(fname);
317 return fn.DynamicInvoke(olist.ToArray());
318 }
319
320 /// <summary>
321 /// Operation to for a region module to register a constant to be used
322 /// by the script engine
323 /// </summary>
324 public void RegisterConstant(string cname, object value)
325 {
326 m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
327 lock (m_constants)
328 {
329 m_constants.Add(cname,value);
330 }
331 }
332
333 public void RegisterConstants(IRegionModuleBase target)
334 {
335 foreach (FieldInfo field in target.GetType().GetFields(
336 BindingFlags.Public | BindingFlags.Static |
337 BindingFlags.Instance))
338 {
339 if (field.GetCustomAttributes(
340 typeof(ScriptConstantAttribute), true).Any())
341 {
342 RegisterConstant(field.Name, field.GetValue(target));
343 }
344 }
345 }
346
347 /// <summary>
348 /// Operation to check for a registered constant
349 /// </summary>
350 public object LookupModConstant(string cname)
351 {
352 // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname);
353
354 lock (m_constants)
355 {
356 object value = null;
357 if (m_constants.TryGetValue(cname,out value))
358 return value;
359 }
360
361 return null;
362 }
363
364 /// <summary>
365 /// Get all registered constants
366 /// </summary>
367 public Dictionary<string, object> GetConstants()
368 {
369 Dictionary<string, object> ret = new Dictionary<string, object>();
370
371 lock (m_constants)
372 {
373 foreach (KeyValuePair<string, object> kvp in m_constants)
374 ret[kvp.Key] = kvp.Value;
375 }
376
377 return ret;
378 }
379
380#endregion
381
382 }
383}
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 9787c8c..41baccc 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,31 +45,292 @@ using OpenSim.Tests.Common.Mock;
45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests 45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
46{ 46{
47 [TestFixture] 47 [TestFixture]
48 public class VectorRenderModuleTests 48 public class VectorRenderModuleTests : OpenSimTestCase
49 { 49 {
50 Scene m_scene;
51 DynamicTextureModule m_dtm;
52 VectorRenderModule m_vrm;
53
54 private void SetupScene(bool reuseTextures)
55 {
56 m_scene = new SceneHelpers().SetupScene();
57
58 m_dtm = new DynamicTextureModule();
59 m_dtm.ReuseTextures = reuseTextures;
60// m_dtm.ReuseLowDataTextures = reuseTextures;
61
62 m_vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
65 }
66
50 [Test] 67 [Test]
51 public void TestDraw() 68 public void TestDraw()
52 { 69 {
53 TestHelpers.InMethod(); 70 TestHelpers.InMethod();
54 71
55 Scene scene = new SceneHelpers().SetupScene(); 72 SetupScene(false);
56 DynamicTextureModule dtm = new DynamicTextureModule(); 73 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
57 VectorRenderModule vrm = new VectorRenderModule();
58 SceneHelpers.SetupSceneModules(scene, dtm, vrm);
59
60 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
61 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 74 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
62 75
63 dtm.AddDynamicTextureData( 76 m_dtm.AddDynamicTextureData(
64 scene.RegionInfo.RegionID, 77 m_scene.RegionInfo.RegionID,
65 so.UUID, 78 so.UUID,
66 vrm.GetContentType(), 79 m_vrm.GetContentType(),
67 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 80 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
68 "", 81 "",
69 0); 82 0);
70 83
84 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
85 }
86
87 [Test]
88 public void TestRepeatSameDraw()
89 {
90 TestHelpers.InMethod();
91
92 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
93
94 SetupScene(false);
95 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
96
97 m_dtm.AddDynamicTextureData(
98 m_scene.RegionInfo.RegionID,
99 so.UUID,
100 m_vrm.GetContentType(),
101 dtText,
102 "",
103 0);
104
105 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
106
107 m_dtm.AddDynamicTextureData(
108 m_scene.RegionInfo.RegionID,
109 so.UUID,
110 m_vrm.GetContentType(),
111 dtText,
112 "",
113 0);
114
115 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
116 }
117
118 [Test]
119 public void TestRepeatSameDrawDifferentExtraParams()
120 {
121 TestHelpers.InMethod();
122
123 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
124
125 SetupScene(false);
126 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
127
128 m_dtm.AddDynamicTextureData(
129 m_scene.RegionInfo.RegionID,
130 so.UUID,
131 m_vrm.GetContentType(),
132 dtText,
133 "",
134 0);
135
136 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
137
138 m_dtm.AddDynamicTextureData(
139 m_scene.RegionInfo.RegionID,
140 so.UUID,
141 m_vrm.GetContentType(),
142 dtText,
143 "alpha:250",
144 0);
145
146 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
147 }
148
149 [Test]
150 public void TestRepeatSameDrawContainingImage()
151 {
152 TestHelpers.InMethod();
153
154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
156
157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
159
160 m_dtm.AddDynamicTextureData(
161 m_scene.RegionInfo.RegionID,
162 so.UUID,
163 m_vrm.GetContentType(),
164 dtText,
165 "",
166 0);
167
168 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
169
170 m_dtm.AddDynamicTextureData(
171 m_scene.RegionInfo.RegionID,
172 so.UUID,
173 m_vrm.GetContentType(),
174 dtText,
175 "",
176 0);
177
178 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
179 }
180
181 [Test]
182 public void TestDrawReusingTexture()
183 {
184 TestHelpers.InMethod();
185
186 SetupScene(true);
187 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
188 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
189
190 m_dtm.AddDynamicTextureData(
191 m_scene.RegionInfo.RegionID,
192 so.UUID,
193 m_vrm.GetContentType(),
194 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
195 "",
196 0);
71 197
72 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 198 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
73 } 199 }
200
201 [Test]
202 public void TestRepeatSameDrawReusingTexture()
203 {
204 TestHelpers.InMethod();
205// TestHelpers.EnableLogging();
206
207 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
208
209 SetupScene(true);
210 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
211
212 m_dtm.AddDynamicTextureData(
213 m_scene.RegionInfo.RegionID,
214 so.UUID,
215 m_vrm.GetContentType(),
216 dtText,
217 "",
218 0);
219
220 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
221
222 m_dtm.AddDynamicTextureData(
223 m_scene.RegionInfo.RegionID,
224 so.UUID,
225 m_vrm.GetContentType(),
226 dtText,
227 "",
228 0);
229
230 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
231 }
232
233 /// <summary>
234 /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
235 /// problems for current viewers.
236 /// </summary>
237 /// <remarks>
238 /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
239 /// texture
240 /// </remarks>
241 [Test]
242 public void TestRepeatSameDrawLowDataTexture()
243 {
244 TestHelpers.InMethod();
245// TestHelpers.EnableLogging();
246
247 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
248
249 SetupScene(true);
250 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
251
252 m_dtm.AddDynamicTextureData(
253 m_scene.RegionInfo.RegionID,
254 so.UUID,
255 m_vrm.GetContentType(),
256 dtText,
257 "1024",
258 0);
259
260 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
261
262 m_dtm.AddDynamicTextureData(
263 m_scene.RegionInfo.RegionID,
264 so.UUID,
265 m_vrm.GetContentType(),
266 dtText,
267 "1024",
268 0);
269
270 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
271 }
272
273 [Test]
274 public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
275 {
276 TestHelpers.InMethod();
277
278 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
279
280 SetupScene(true);
281 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
282
283 m_dtm.AddDynamicTextureData(
284 m_scene.RegionInfo.RegionID,
285 so.UUID,
286 m_vrm.GetContentType(),
287 dtText,
288 "",
289 0);
290
291 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
292
293 m_dtm.AddDynamicTextureData(
294 m_scene.RegionInfo.RegionID,
295 so.UUID,
296 m_vrm.GetContentType(),
297 dtText,
298 "alpha:250",
299 0);
300
301 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
302 }
303
304 [Test]
305 public void TestRepeatSameDrawContainingImageReusingTexture()
306 {
307 TestHelpers.InMethod();
308
309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
311
312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
314
315 m_dtm.AddDynamicTextureData(
316 m_scene.RegionInfo.RegionID,
317 so.UUID,
318 m_vrm.GetContentType(),
319 dtText,
320 "",
321 0);
322
323 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
324
325 m_dtm.AddDynamicTextureData(
326 m_scene.RegionInfo.RegionID,
327 so.UUID,
328 m_vrm.GetContentType(),
329 dtText,
330 "",
331 0);
332
333 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
334 }
74 } 335 }
75} \ No newline at end of file 336} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 8b2f2f8..f395441 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,26 +30,35 @@ using System.Drawing;
30using System.Drawing.Imaging; 30using System.Drawing.Imaging;
31using System.Globalization; 31using System.Globalization;
32using System.IO; 32using System.IO;
33using System.Linq;
33using System.Net; 34using System.Net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenMetaverse.Imaging; 37using OpenMetaverse.Imaging;
38using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
37using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using log4net; 41using log4net;
40using System.Reflection; 42using System.Reflection;
43using Mono.Addins;
41 44
42//using Cairo; 45//using Cairo;
43 46
44namespace OpenSim.Region.CoreModules.Scripting.VectorRender 47namespace OpenSim.Region.CoreModules.Scripting.VectorRender
45{ 48{
46 public class VectorRenderModule : IRegionModule, IDynamicTextureRender 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VectorRenderModule")]
50 public class VectorRenderModule : ISharedRegionModule, IDynamicTextureRender
47 { 51 {
52 // These fields exist for testing purposes, please do not remove.
53// private static bool s_flipper;
54// private static byte[] s_asset1Data;
55// private static byte[] s_asset2Data;
56
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 58
50 private string m_name = "VectorRenderModule";
51 private Scene m_scene; 59 private Scene m_scene;
52 private IDynamicTextureManager m_textureManager; 60 private IDynamicTextureManager m_textureManager;
61
53 private Graphics m_graph; 62 private Graphics m_graph;
54 private string m_fontName = "Arial"; 63 private string m_fontName = "Arial";
55 64
@@ -61,12 +70,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
61 70
62 public string GetContentType() 71 public string GetContentType()
63 { 72 {
64 return ("vector"); 73 return "vector";
65 } 74 }
66 75
67 public string GetName() 76 public string GetName()
68 { 77 {
69 return m_name; 78 return Name;
70 } 79 }
71 80
72 public bool SupportsAsynchronous() 81 public bool SupportsAsynchronous()
@@ -74,14 +83,20 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
74 return true; 83 return true;
75 } 84 }
76 85
77 public byte[] ConvertUrl(string url, string extraParams) 86// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
87// {
88// string[] lines = GetLines(bodyData);
89// return lines.Any((str, r) => str.StartsWith("Image"));
90// }
91
92 public IDynamicTexture ConvertUrl(string url, string extraParams)
78 { 93 {
79 return null; 94 return null;
80 } 95 }
81 96
82 public byte[] ConvertStream(Stream data, string extraParams) 97 public IDynamicTexture ConvertData(string bodyData, string extraParams)
83 { 98 {
84 return null; 99 return Draw(bodyData, extraParams);
85 } 100 }
86 101
87 public bool AsyncConvertUrl(UUID id, string url, string extraParams) 102 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -91,78 +106,101 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
91 106
92 public bool AsyncConvertData(UUID id, string bodyData, string extraParams) 107 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
93 { 108 {
94 Draw(bodyData, id, extraParams); 109 if (m_textureManager == null)
110 {
111 m_log.Warn("[VECTORRENDERMODULE]: No texture manager. Can't function");
112 return false;
113 }
114 // XXX: This isn't actually being done asynchronously!
115 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
116
95 return true; 117 return true;
96 } 118 }
97 119
98 public void GetDrawStringSize(string text, string fontName, int fontSize, 120 public void GetDrawStringSize(string text, string fontName, int fontSize,
99 out double xSize, out double ySize) 121 out double xSize, out double ySize)
100 { 122 {
101 using (Font myFont = new Font(fontName, fontSize)) 123 lock (this)
102 { 124 {
103 SizeF stringSize = new SizeF(); 125 using (Font myFont = new Font(fontName, fontSize))
104 lock (m_graph)
105 { 126 {
106 stringSize = m_graph.MeasureString(text, myFont); 127 SizeF stringSize = new SizeF();
107 xSize = stringSize.Width; 128
108 ySize = stringSize.Height; 129 // XXX: This lock may be unnecessary.
130 lock (m_graph)
131 {
132 stringSize = m_graph.MeasureString(text, myFont);
133 xSize = stringSize.Width;
134 ySize = stringSize.Height;
135 }
109 } 136 }
110 } 137 }
111 } 138 }
112 139
113 #endregion 140 #endregion
114 141
115 #region IRegionModule Members 142 #region ISharedRegionModule Members
116 143
117 public void Initialise(Scene scene, IConfigSource config) 144 public void Initialise(IConfigSource config)
118 { 145 {
119 if (m_scene == null)
120 {
121 m_scene = scene;
122 }
123
124 if (m_graph == null)
125 {
126 // We won't dispose of these explicitly since this module is only removed when the entire simulator
127 // is shut down.
128 Bitmap bitmap = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb);
129 m_graph = Graphics.FromImage(bitmap);
130 }
131
132 IConfig cfg = config.Configs["VectorRender"]; 146 IConfig cfg = config.Configs["VectorRender"];
133 if (null != cfg) 147 if (null != cfg)
134 { 148 {
135 m_fontName = cfg.GetString("font_name", m_fontName); 149 m_fontName = cfg.GetString("font_name", m_fontName);
136 } 150 }
137 m_log.DebugFormat("[VECTORRENDERMODULE]: using font \"{0}\" for text rendering.", m_fontName); 151 m_log.DebugFormat("[VECTORRENDERMODULE]: using font \"{0}\" for text rendering.", m_fontName);
152
153 // We won't dispose of these explicitly since this module is only removed when the entire simulator
154 // is shut down.
155 Bitmap bitmap = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb);
156 m_graph = Graphics.FromImage(bitmap);
138 } 157 }
139 158
140 public void PostInitialise() 159 public void PostInitialise()
141 { 160 {
142 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>(); 161 }
143 if (m_textureManager != null) 162
163 public void AddRegion(Scene scene)
164 {
165 if (m_scene == null)
144 { 166 {
145 m_textureManager.RegisterRender(GetContentType(), this); 167 m_scene = scene;
146 } 168 }
147 } 169 }
148 170
171 public void RegionLoaded(Scene scene)
172 {
173 if (m_textureManager == null && m_scene == scene)
174 {
175 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
176 if (m_textureManager != null)
177 {
178 m_textureManager.RegisterRender(GetContentType(), this);
179 }
180 }
181 }
182
183 public void RemoveRegion(Scene scene)
184 {
185 }
186
149 public void Close() 187 public void Close()
150 { 188 {
151 } 189 }
152 190
153 public string Name 191 public string Name
154 { 192 {
155 get { return m_name; } 193 get { return "VectorRenderModule"; }
156 } 194 }
157 195
158 public bool IsSharedModule 196 public Type ReplaceableInterface
159 { 197 {
160 get { return true; } 198 get { return null; }
161 } 199 }
162 200
163 #endregion 201 #endregion
164 202
165 private void Draw(string data, UUID id, string extraParams) 203 private IDynamicTexture Draw(string data, string extraParams)
166 { 204 {
167 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha 205 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
168 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 206 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -305,40 +343,57 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
305 343
306 Bitmap bitmap = null; 344 Bitmap bitmap = null;
307 Graphics graph = null; 345 Graphics graph = null;
346 bool reuseable = false;
308 347
309 try 348 try
310 { 349 {
311 if (alpha == 256) 350 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
312 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); 351 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
313 else 352 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
314 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 353 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
315 354 // under lock.
316 graph = Graphics.FromImage(bitmap); 355 lock (this)
317
318 // this is really just to save people filling the
319 // background color in their scripts, only do when fully opaque
320 if (alpha >= 255)
321 { 356 {
322 using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) 357 if (alpha == 256)
358 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
359 else
360 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
361
362 graph = Graphics.FromImage(bitmap);
363
364 // this is really just to save people filling the
365 // background color in their scripts, only do when fully opaque
366 if (alpha >= 255)
323 { 367 {
324 graph.FillRectangle(bgFillBrush, 0, 0, width, height); 368 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
369 {
370 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
371 }
325 } 372 }
326 } 373
327 374 for (int w = 0; w < bitmap.Width; w++)
328 for (int w = 0; w < bitmap.Width; w++)
329 {
330 if (alpha <= 255)
331 { 375 {
332 for (int h = 0; h < bitmap.Height; h++) 376 if (alpha <= 255)
333 { 377 {
334 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); 378 for (int h = 0; h < bitmap.Height; h++)
379 {
380 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
381 }
335 } 382 }
336 } 383 }
384
385 GDIDraw(data, graph, altDataDelim, out reuseable);
337 } 386 }
338 387
339 GDIDraw(data, graph, altDataDelim);
340
341 byte[] imageJ2000 = new byte[0]; 388 byte[] imageJ2000 = new byte[0];
389
390 // This code exists for testing purposes, please do not remove.
391// if (s_flipper)
392// imageJ2000 = s_asset1Data;
393// else
394// imageJ2000 = s_asset2Data;
395//
396// s_flipper = !s_flipper;
342 397
343 try 398 try
344 { 399 {
@@ -351,15 +406,24 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
351 e.Message, e.StackTrace); 406 e.Message, e.StackTrace);
352 } 407 }
353 408
354 m_textureManager.ReturnData(id, imageJ2000); 409 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
410 data, extraParams, imageJ2000, new Size(width, height), reuseable);
355 } 411 }
356 finally 412 finally
357 { 413 {
358 if (graph != null) 414 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
359 graph.Dispose(); 415 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
360 416 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
361 if (bitmap != null) 417 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
362 bitmap.Dispose(); 418 // under lock.
419 lock (this)
420 {
421 if (graph != null)
422 graph.Dispose();
423
424 if (bitmap != null)
425 bitmap.Dispose();
426 }
363 } 427 }
364 } 428 }
365 429
@@ -418,8 +482,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
418 } 482 }
419*/ 483*/
420 484
421 private void GDIDraw(string data, Graphics graph, char dataDelim) 485 /// <summary>
486 /// Split input data into discrete command lines.
487 /// </summary>
488 /// <returns></returns>
489 /// <param name='data'></param>
490 /// <param name='dataDelim'></param>
491 private string[] GetLines(string data, char dataDelim)
492 {
493 char[] lineDelimiter = { dataDelim };
494 return data.Split(lineDelimiter);
495 }
496
497 private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
422 { 498 {
499 reuseable = true;
423 Point startPoint = new Point(0, 0); 500 Point startPoint = new Point(0, 0);
424 Point endPoint = new Point(0, 0); 501 Point endPoint = new Point(0, 0);
425 Pen drawPen = null; 502 Pen drawPen = null;
@@ -434,11 +511,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
434 myFont = new Font(fontName, fontSize); 511 myFont = new Font(fontName, fontSize);
435 myBrush = new SolidBrush(Color.Black); 512 myBrush = new SolidBrush(Color.Black);
436 513
437 char[] lineDelimiter = {dataDelim};
438 char[] partsDelimiter = {','}; 514 char[] partsDelimiter = {','};
439 string[] lines = data.Split(lineDelimiter);
440 515
441 foreach (string line in lines) 516 foreach (string line in GetLines(data, dataDelim))
442 { 517 {
443 string nextLine = line.Trim(); 518 string nextLine = line.Trim();
444 //replace with switch, or even better, do some proper parsing 519 //replace with switch, or even better, do some proper parsing
@@ -469,6 +544,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
469 } 544 }
470 else if (nextLine.StartsWith("Image")) 545 else if (nextLine.StartsWith("Image"))
471 { 546 {
547 // We cannot reuse any generated texture involving fetching an image via HTTP since that image
548 // can change.
549 reuseable = false;
550
472 float x = 0; 551 float x = 0;
473 float y = 0; 552 float y = 0;
474 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); 553 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index 07bb291..87a0537 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -28,8 +28,13 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Text.RegularExpressions;
32
31using Nini.Config; 33using Nini.Config;
34using Mono.Addins;
35
32using OpenMetaverse; 36using OpenMetaverse;
37
33using OpenSim.Framework; 38using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
@@ -85,7 +90,8 @@ using OpenSim.Region.Framework.Scenes;
85 90
86namespace OpenSim.Region.CoreModules.Scripting.WorldComm 91namespace OpenSim.Region.CoreModules.Scripting.WorldComm
87{ 92{
88 public class WorldCommModule : IRegionModule, IWorldComm 93 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldCommModule")]
94 public class WorldCommModule : IWorldComm, INonSharedRegionModule
89 { 95 {
90 // private static readonly ILog m_log = 96 // private static readonly ILog m_log =
91 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 97 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -100,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
100 private int m_saydistance = 20; 106 private int m_saydistance = 20;
101 private int m_shoutdistance = 100; 107 private int m_shoutdistance = 100;
102 108
103 #region IRegionModule Members 109 #region INonSharedRegionModule Members
104 110
105 public void Initialise(Scene scene, IConfigSource config) 111 public void Initialise(IConfigSource config)
106 { 112 {
107 // wrap this in a try block so that defaults will work if 113 // wrap this in a try block so that defaults will work if
108 // the config file doesn't specify otherwise. 114 // the config file doesn't specify otherwise.
@@ -110,29 +116,49 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
110 int maxhandles = 64; 116 int maxhandles = 64;
111 try 117 try
112 { 118 {
113 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 119 m_whisperdistance = config.Configs["Chat"].GetInt(
114 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 120 "whisper_distance", m_whisperdistance);
115 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 121 m_saydistance = config.Configs["Chat"].GetInt(
116 maxlisteners = config.Configs["LL-Functions"].GetInt("max_listens_per_region", maxlisteners); 122 "say_distance", m_saydistance);
117 maxhandles = config.Configs["LL-Functions"].GetInt("max_listens_per_script", maxhandles); 123 m_shoutdistance = config.Configs["Chat"].GetInt(
124 "shout_distance", m_shoutdistance);
125 maxlisteners = config.Configs["LL-Functions"].GetInt(
126 "max_listens_per_region", maxlisteners);
127 maxhandles = config.Configs["LL-Functions"].GetInt(
128 "max_listens_per_script", maxhandles);
118 } 129 }
119 catch (Exception) 130 catch (Exception)
120 { 131 {
121 } 132 }
122 if (maxlisteners < 1) maxlisteners = int.MaxValue; 133 if (maxlisteners < 1) maxlisteners = int.MaxValue;
123 if (maxhandles < 1) maxhandles = int.MaxValue; 134 if (maxhandles < 1) maxhandles = int.MaxValue;
135 m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
136 m_pendingQ = new Queue();
137 m_pending = Queue.Synchronized(m_pendingQ);
138 }
124 139
140 public void PostInitialise()
141 {
142 }
143
144 public void AddRegion(Scene scene)
145 {
125 m_scene = scene; 146 m_scene = scene;
126 m_scene.RegisterModuleInterface<IWorldComm>(this); 147 m_scene.RegisterModuleInterface<IWorldComm>(this);
127 m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
128 m_scene.EventManager.OnChatFromClient += DeliverClientMessage; 148 m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
129 m_scene.EventManager.OnChatBroadcast += DeliverClientMessage; 149 m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
130 m_pendingQ = new Queue();
131 m_pending = Queue.Synchronized(m_pendingQ);
132 } 150 }
133 151
134 public void PostInitialise() 152 public void RegionLoaded(Scene scene) { }
153
154 public void RemoveRegion(Scene scene)
135 { 155 {
156 if (scene != m_scene)
157 return;
158
159 m_scene.UnregisterModuleInterface<IWorldComm>(this);
160 m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage;
161 m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage;
136 } 162 }
137 163
138 public void Close() 164 public void Close()
@@ -144,10 +170,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
144 get { return "WorldCommModule"; } 170 get { return "WorldCommModule"; }
145 } 171 }
146 172
147 public bool IsSharedModule 173 public Type ReplaceableInterface { get { return null; } }
148 {
149 get { return false; }
150 }
151 174
152 #endregion 175 #endregion
153 176
@@ -172,12 +195,42 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
172 /// <param name="hostID">UUID of the SceneObjectPart</param> 195 /// <param name="hostID">UUID of the SceneObjectPart</param>
173 /// <param name="channel">channel to listen on</param> 196 /// <param name="channel">channel to listen on</param>
174 /// <param name="name">name to filter on</param> 197 /// <param name="name">name to filter on</param>
175 /// <param name="id">key to filter on (user given, could be totally faked)</param> 198 /// <param name="id">
199 /// key to filter on (user given, could be totally faked)
200 /// </param>
201 /// <param name="msg">msg to filter on</param>
202 /// <returns>number of the scripts handle</returns>
203 public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
204 string name, UUID id, string msg)
205 {
206 return m_listenerManager.AddListener(localID, itemID, hostID,
207 channel, name, id, msg);
208 }
209
210 /// <summary>
211 /// Create a listen event callback with the specified filters.
212 /// The parameters localID,itemID are needed to uniquely identify
213 /// the script during 'peek' time. Parameter hostID is needed to
214 /// determine the position of the script.
215 /// </summary>
216 /// <param name="localID">localID of the script engine</param>
217 /// <param name="itemID">UUID of the script engine</param>
218 /// <param name="hostID">UUID of the SceneObjectPart</param>
219 /// <param name="channel">channel to listen on</param>
220 /// <param name="name">name to filter on</param>
221 /// <param name="id">
222 /// key to filter on (user given, could be totally faked)
223 /// </param>
176 /// <param name="msg">msg to filter on</param> 224 /// <param name="msg">msg to filter on</param>
225 /// <param name="regexBitfield">
226 /// Bitfield indicating which strings should be processed as regex.
227 /// </param>
177 /// <returns>number of the scripts handle</returns> 228 /// <returns>number of the scripts handle</returns>
178 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) 229 public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
230 string name, UUID id, string msg, int regexBitfield)
179 { 231 {
180 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); 232 return m_listenerManager.AddListener(localID, itemID, hostID,
233 channel, name, id, msg, regexBitfield);
181 } 234 }
182 235
183 /// <summary> 236 /// <summary>
@@ -226,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
226 279
227 if ((source = m_scene.GetSceneObjectPart(id)) != null) 280 if ((source = m_scene.GetSceneObjectPart(id)) != null)
228 position = source.AbsolutePosition; 281 position = source.AbsolutePosition;
229 else if ((avatar = m_scene.GetScenePresence(id)) != null) 282 else if ((avatar = m_scene.GetScenePresence(id)) != null)
230 position = avatar.AbsolutePosition; 283 position = avatar.AbsolutePosition;
231 else if (ChatTypeEnum.Region == type) 284 else if (ChatTypeEnum.Region == type)
232 position = CenterOfRegion; 285 position = CenterOfRegion;
@@ -249,7 +302,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
249 /// <param name="name">name of sender (object or avatar)</param> 302 /// <param name="name">name of sender (object or avatar)</param>
250 /// <param name="id">key of sender (object or avatar)</param> 303 /// <param name="id">key of sender (object or avatar)</param>
251 /// <param name="msg">msg to sent</param> 304 /// <param name="msg">msg to sent</param>
252 public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position) 305 public void DeliverMessage(ChatTypeEnum type, int channel,
306 string name, UUID id, string msg, Vector3 position)
253 { 307 {
254 // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}", 308 // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
255 // type, channel, name, id, msg); 309 // type, channel, name, id, msg);
@@ -257,17 +311,21 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
257 // Determine which listen event filters match the given set of arguments, this results 311 // Determine which listen event filters match the given set of arguments, this results
258 // in a limited set of listeners, each belonging a host. If the host is in range, add them 312 // in a limited set of listeners, each belonging a host. If the host is in range, add them
259 // to the pending queue. 313 // to the pending queue.
260 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) 314 foreach (ListenerInfo li
315 in m_listenerManager.GetListeners(UUID.Zero, channel,
316 name, id, msg))
261 { 317 {
262 // Dont process if this message is from yourself! 318 // Dont process if this message is from yourself!
263 if (li.GetHostID().Equals(id)) 319 if (li.GetHostID().Equals(id))
264 continue; 320 continue;
265 321
266 SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); 322 SceneObjectPart sPart = m_scene.GetSceneObjectPart(
323 li.GetHostID());
267 if (sPart == null) 324 if (sPart == null)
268 continue; 325 continue;
269 326
270 double dis = Util.GetDistanceTo(sPart.AbsolutePosition, position); 327 double dis = Util.GetDistanceTo(sPart.AbsolutePosition,
328 position);
271 switch (type) 329 switch (type)
272 { 330 {
273 case ChatTypeEnum.Whisper: 331 case ChatTypeEnum.Whisper:
@@ -326,7 +384,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
326 if (channel == 0) 384 if (channel == 0)
327 { 385 {
328 // Channel 0 goes to viewer ONLY 386 // Channel 0 goes to viewer ONLY
329 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); 387 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
330 return true; 388 return true;
331 } 389 }
332 390
@@ -369,11 +427,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
369 if (li.GetHostID().Equals(id)) 427 if (li.GetHostID().Equals(id))
370 continue; 428 continue;
371 429
372 SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); 430 SceneObjectPart sPart = m_scene.GetSceneObjectPart(
431 li.GetHostID());
373 if (sPart == null) 432 if (sPart == null)
374 continue; 433 continue;
375 434
376 if ( li.GetHostID().Equals(target)) 435 if (li.GetHostID().Equals(target))
377 { 436 {
378 QueueMessage(new ListenerInfo(li, name, id, msg)); 437 QueueMessage(new ListenerInfo(li, name, id, msg));
379 break; 438 break;
@@ -427,9 +486,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
427 private void DeliverClientMessage(Object sender, OSChatMessage e) 486 private void DeliverClientMessage(Object sender, OSChatMessage e)
428 { 487 {
429 if (null != e.Sender) 488 if (null != e.Sender)
430 DeliverMessage(e.Type, e.Channel, e.Sender.Name, e.Sender.AgentId, e.Message, e.Position); 489 {
490 DeliverMessage(e.Type, e.Channel, e.Sender.Name,
491 e.Sender.AgentId, e.Message, e.Position);
492 }
431 else 493 else
432 DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero, e.Message, e.Position); 494 {
495 DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero,
496 e.Message, e.Position);
497 }
433 } 498 }
434 499
435 public Object[] GetSerializationData(UUID itemID) 500 public Object[] GetSerializationData(UUID itemID)
@@ -446,7 +511,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
446 511
447 public class ListenerManager 512 public class ListenerManager
448 { 513 {
449 private Dictionary<int, List<ListenerInfo>> m_listeners = new Dictionary<int, List<ListenerInfo>>(); 514 private Dictionary<int, List<ListenerInfo>> m_listeners =
515 new Dictionary<int, List<ListenerInfo>>();
450 private int m_maxlisteners; 516 private int m_maxlisteners;
451 private int m_maxhandles; 517 private int m_maxhandles;
452 private int m_curlisteners; 518 private int m_curlisteners;
@@ -470,15 +536,25 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
470 m_curlisteners = 0; 536 m_curlisteners = 0;
471 } 537 }
472 538
473 public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) 539 public int AddListener(uint localID, UUID itemID, UUID hostID,
540 int channel, string name, UUID id, string msg)
541 {
542 return AddListener(localID, itemID, hostID, channel, name, id,
543 msg, 0);
544 }
545
546 public int AddListener(uint localID, UUID itemID, UUID hostID,
547 int channel, string name, UUID id, string msg,
548 int regexBitfield)
474 { 549 {
475 // do we already have a match on this particular filter event? 550 // do we already have a match on this particular filter event?
476 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg); 551 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id,
552 msg);
477 553
478 if (coll.Count > 0) 554 if (coll.Count > 0)
479 { 555 {
480 // special case, called with same filter settings, return same handle 556 // special case, called with same filter settings, return same
481 // (2008-05-02, tested on 1.21.1 server, still holds) 557 // handle (2008-05-02, tested on 1.21.1 server, still holds)
482 return coll[0].GetHandle(); 558 return coll[0].GetHandle();
483 } 559 }
484 560
@@ -490,16 +566,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
490 566
491 if (newHandle > 0) 567 if (newHandle > 0)
492 { 568 {
493 ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); 569 ListenerInfo li = new ListenerInfo(newHandle, localID,
570 itemID, hostID, channel, name, id, msg,
571 regexBitfield);
494 572
495 List<ListenerInfo> listeners; 573 List<ListenerInfo> listeners;
496 if (!m_listeners.TryGetValue(channel,out listeners)) 574 if (!m_listeners.TryGetValue(
497 { 575 channel, out listeners))
498 listeners = new List<ListenerInfo>(); 576 {
499 m_listeners.Add(channel, listeners); 577 listeners = new List<ListenerInfo>();
500 } 578 m_listeners.Add(channel, listeners);
501 listeners.Add(li); 579 }
502 m_curlisteners++; 580 listeners.Add(li);
581 m_curlisteners++;
503 582
504 return newHandle; 583 return newHandle;
505 } 584 }
@@ -512,11 +591,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
512 { 591 {
513 lock (m_listeners) 592 lock (m_listeners)
514 { 593 {
515 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 594 foreach (KeyValuePair<int, List<ListenerInfo>> lis
595 in m_listeners)
516 { 596 {
517 foreach (ListenerInfo li in lis.Value) 597 foreach (ListenerInfo li in lis.Value)
518 { 598 {
519 if (li.GetItemID().Equals(itemID) && li.GetHandle().Equals(handle)) 599 if (li.GetItemID().Equals(itemID) &&
600 li.GetHandle().Equals(handle))
520 { 601 {
521 lis.Value.Remove(li); 602 lis.Value.Remove(li);
522 if (lis.Value.Count == 0) 603 if (lis.Value.Count == 0)
@@ -539,13 +620,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
539 620
540 lock (m_listeners) 621 lock (m_listeners)
541 { 622 {
542 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 623 foreach (KeyValuePair<int, List<ListenerInfo>> lis
624 in m_listeners)
543 { 625 {
544 foreach (ListenerInfo li in lis.Value) 626 foreach (ListenerInfo li in lis.Value)
545 { 627 {
546 if (li.GetItemID().Equals(itemID)) 628 if (li.GetItemID().Equals(itemID))
547 { 629 {
548 // store them first, else the enumerated bails on us 630 // store them first, else the enumerated bails on
631 // us
549 removedListeners.Add(li); 632 removedListeners.Add(li);
550 } 633 }
551 } 634 }
@@ -572,11 +655,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
572 { 655 {
573 lock (m_listeners) 656 lock (m_listeners)
574 { 657 {
575 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 658 foreach (KeyValuePair<int, List<ListenerInfo>> lis
659 in m_listeners)
576 { 660 {
577 foreach (ListenerInfo li in lis.Value) 661 foreach (ListenerInfo li in lis.Value)
578 { 662 {
579 if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) 663 if (li.GetItemID().Equals(itemID) &&
664 li.GetHandle() == handle)
580 { 665 {
581 li.Activate(); 666 li.Activate();
582 // only one, bail out 667 // only one, bail out
@@ -591,11 +676,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
591 { 676 {
592 lock (m_listeners) 677 lock (m_listeners)
593 { 678 {
594 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 679 foreach (KeyValuePair<int, List<ListenerInfo>> lis
680 in m_listeners)
595 { 681 {
596 foreach (ListenerInfo li in lis.Value) 682 foreach (ListenerInfo li in lis.Value)
597 { 683 {
598 if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) 684 if (li.GetItemID().Equals(itemID) &&
685 li.GetHandle() == handle)
599 { 686 {
600 li.Deactivate(); 687 li.Deactivate();
601 // only one, bail out 688 // only one, bail out
@@ -606,19 +693,24 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
606 } 693 }
607 } 694 }
608 695
609 // non-locked access, since its always called in the context of the lock 696 /// <summary>
697 /// non-locked access, since its always called in the context of the
698 /// lock
699 /// </summary>
700 /// <param name="itemID"></param>
701 /// <returns></returns>
610 private int GetNewHandle(UUID itemID) 702 private int GetNewHandle(UUID itemID)
611 { 703 {
612 List<int> handles = new List<int>(); 704 List<int> handles = new List<int>();
613 705
614 // build a list of used keys for this specific itemID... 706 // build a list of used keys for this specific itemID...
615 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 707 foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listeners)
616 { 708 {
617 foreach (ListenerInfo li in lis.Value) 709 foreach (ListenerInfo li in lis.Value)
618 { 710 {
619 if (li.GetItemID().Equals(itemID)) 711 if (li.GetItemID().Equals(itemID))
620 handles.Add(li.GetHandle()); 712 handles.Add(li.GetHandle());
621 } 713 }
622 } 714 }
623 715
624 // Note: 0 is NOT a valid handle for llListen() to return 716 // Note: 0 is NOT a valid handle for llListen() to return
@@ -631,17 +723,46 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
631 return -1; 723 return -1;
632 } 724 }
633 725
634 // Theres probably a more clever and efficient way to 726 /// These are duplicated from ScriptBaseClass
635 // do this, maybe with regex. 727 /// http://opensimulator.org/mantis/view.php?id=6106#c21945
636 // PM2008: Ha, one could even be smart and define a specialized Enumerator. 728 #region Constants for the bitfield parameter of osListenRegex
637 public List<ListenerInfo> GetListeners(UUID itemID, int channel, string name, UUID id, string msg) 729
730 /// <summary>
731 /// process name parameter as regex
732 /// </summary>
733 public const int OS_LISTEN_REGEX_NAME = 0x1;
734
735 /// <summary>
736 /// process message parameter as regex
737 /// </summary>
738 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
739
740 #endregion
741
742 /// <summary>
743 /// Get listeners matching the input parameters.
744 /// </summary>
745 /// <remarks>
746 /// Theres probably a more clever and efficient way to do this, maybe
747 /// with regex.
748 /// PM2008: Ha, one could even be smart and define a specialized
749 /// Enumerator.
750 /// </remarks>
751 /// <param name="itemID"></param>
752 /// <param name="channel"></param>
753 /// <param name="name"></param>
754 /// <param name="id"></param>
755 /// <param name="msg"></param>
756 /// <returns></returns>
757 public List<ListenerInfo> GetListeners(UUID itemID, int channel,
758 string name, UUID id, string msg)
638 { 759 {
639 List<ListenerInfo> collection = new List<ListenerInfo>(); 760 List<ListenerInfo> collection = new List<ListenerInfo>();
640 761
641 lock (m_listeners) 762 lock (m_listeners)
642 { 763 {
643 List<ListenerInfo> listeners; 764 List<ListenerInfo> listeners;
644 if (!m_listeners.TryGetValue(channel,out listeners)) 765 if (!m_listeners.TryGetValue(channel, out listeners))
645 { 766 {
646 return collection; 767 return collection;
647 } 768 }
@@ -652,11 +773,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
652 { 773 {
653 continue; 774 continue;
654 } 775 }
655 if (!itemID.Equals(UUID.Zero) && !li.GetItemID().Equals(itemID)) 776 if (!itemID.Equals(UUID.Zero) &&
777 !li.GetItemID().Equals(itemID))
656 { 778 {
657 continue; 779 continue;
658 } 780 }
659 if (li.GetName().Length > 0 && !li.GetName().Equals(name)) 781 if (li.GetName().Length > 0 && (
782 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) ||
783 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName()))
784 ))
660 { 785 {
661 continue; 786 continue;
662 } 787 }
@@ -664,7 +789,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
664 { 789 {
665 continue; 790 continue;
666 } 791 }
667 if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) 792 if (li.GetMessage().Length > 0 && (
793 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) ||
794 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage()))
795 ))
668 { 796 {
669 continue; 797 continue;
670 } 798 }
@@ -697,10 +825,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
697 { 825 {
698 int idx = 0; 826 int idx = 0;
699 Object[] item = new Object[6]; 827 Object[] item = new Object[6];
828 int dataItemLength = 6;
700 829
701 while (idx < data.Length) 830 while (idx < data.Length)
702 { 831 {
703 Array.Copy(data, idx, item, 0, 6); 832 dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6;
833 item = new Object[dataItemLength];
834 Array.Copy(data, idx, item, 0, dataItemLength);
704 835
705 ListenerInfo info = 836 ListenerInfo info =
706 ListenerInfo.FromData(localID, itemID, hostID, item); 837 ListenerInfo.FromData(localID, itemID, hostID, item);
@@ -708,39 +839,98 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
708 lock (m_listeners) 839 lock (m_listeners)
709 { 840 {
710 if (!m_listeners.ContainsKey((int)item[2])) 841 if (!m_listeners.ContainsKey((int)item[2]))
711 m_listeners.Add((int)item[2], new List<ListenerInfo>()); 842 {
843 m_listeners.Add((int)item[2],
844 new List<ListenerInfo>());
845 }
712 m_listeners[(int)item[2]].Add(info); 846 m_listeners[(int)item[2]].Add(info);
713 } 847 }
714 848
715 idx+=6; 849 idx += dataItemLength;
716 } 850 }
717 } 851 }
718 } 852 }
719 853
720 public class ListenerInfo: IWorldCommListenerInfo 854 public class ListenerInfo : IWorldCommListenerInfo
721 { 855 {
722 private bool m_active; // Listener is active or not 856 /// <summary>
723 private int m_handle; // Assigned handle of this listener 857 /// Listener is active or not
724 private uint m_localID; // Local ID from script engine 858 /// </summary>
725 private UUID m_itemID; // ID of the host script engine 859 private bool m_active;
726 private UUID m_hostID; // ID of the host/scene part 860
727 private int m_channel; // Channel 861 /// <summary>
728 private UUID m_id; // ID to filter messages from 862 /// Assigned handle of this listener
729 private string m_name; // Object name to filter messages from 863 /// </summary>
730 private string m_message; // The message 864 private int m_handle;
865
866 /// <summary>
867 /// Local ID from script engine
868 /// </summary>
869 private uint m_localID;
870
871 /// <summary>
872 /// ID of the host script engine
873 /// </summary>
874 private UUID m_itemID;
875
876 /// <summary>
877 /// ID of the host/scene part
878 /// </summary>
879 private UUID m_hostID;
880
881 /// <summary>
882 /// Channel
883 /// </summary>
884 private int m_channel;
885
886 /// <summary>
887 /// ID to filter messages from
888 /// </summary>
889 private UUID m_id;
890
891 /// <summary>
892 /// Object name to filter messages from
893 /// </summary>
894 private string m_name;
895
896 /// <summary>
897 /// The message
898 /// </summary>
899 private string m_message;
900
901 public ListenerInfo(int handle, uint localID, UUID ItemID,
902 UUID hostID, int channel, string name, UUID id,
903 string message)
904 {
905 Initialise(handle, localID, ItemID, hostID, channel, name, id,
906 message, 0);
907 }
731 908
732 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) 909 public ListenerInfo(int handle, uint localID, UUID ItemID,
910 UUID hostID, int channel, string name, UUID id,
911 string message, int regexBitfield)
733 { 912 {
734 Initialise(handle, localID, ItemID, hostID, channel, name, id, message); 913 Initialise(handle, localID, ItemID, hostID, channel, name, id,
914 message, regexBitfield);
735 } 915 }
736 916
737 public ListenerInfo(ListenerInfo li, string name, UUID id, string message) 917 public ListenerInfo(ListenerInfo li, string name, UUID id,
918 string message)
738 { 919 {
739 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); 920 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID,
921 li.m_channel, name, id, message, 0);
740 } 922 }
741 923
742 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, 924 public ListenerInfo(ListenerInfo li, string name, UUID id,
743 UUID id, string message) 925 string message, int regexBitfield)
926 {
927 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID,
928 li.m_channel, name, id, message, regexBitfield);
929 }
930
931 private void Initialise(int handle, uint localID, UUID ItemID,
932 UUID hostID, int channel, string name, UUID id,
933 string message, int regexBitfield)
744 { 934 {
745 m_active = true; 935 m_active = true;
746 m_handle = handle; 936 m_handle = handle;
@@ -751,11 +941,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
751 m_name = name; 941 m_name = name;
752 m_id = id; 942 m_id = id;
753 m_message = message; 943 m_message = message;
944 RegexBitfield = regexBitfield;
754 } 945 }
755 946
756 public Object[] GetSerializationData() 947 public Object[] GetSerializationData()
757 { 948 {
758 Object[] data = new Object[6]; 949 Object[] data = new Object[7];
759 950
760 data[0] = m_active; 951 data[0] = m_active;
761 data[1] = m_handle; 952 data[1] = m_handle;
@@ -763,16 +954,22 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
763 data[3] = m_name; 954 data[3] = m_name;
764 data[4] = m_id; 955 data[4] = m_id;
765 data[5] = m_message; 956 data[5] = m_message;
957 data[6] = RegexBitfield;
766 958
767 return data; 959 return data;
768 } 960 }
769 961
770 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) 962 public static ListenerInfo FromData(uint localID, UUID ItemID,
963 UUID hostID, Object[] data)
771 { 964 {
772 ListenerInfo linfo = new ListenerInfo((int)data[1], localID, 965 ListenerInfo linfo = new ListenerInfo((int)data[1], localID,
773 ItemID, hostID, (int)data[2], (string)data[3], 966 ItemID, hostID, (int)data[2], (string)data[3],
774 (UUID)data[4], (string)data[5]); 967 (UUID)data[4], (string)data[5]);
775 linfo.m_active=(bool)data[0]; 968 linfo.m_active = (bool)data[0];
969 if (data.Length >= 7)
970 {
971 linfo.RegexBitfield = (int)data[6];
972 }
776 973
777 return linfo; 974 return linfo;
778 } 975 }
@@ -831,5 +1028,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
831 { 1028 {
832 return m_id; 1029 return m_id;
833 } 1030 }
1031
1032 public int RegexBitfield { get; private set; }
834 } 1033 }
835} 1034}
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index 0003af2..385f5ad 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer; 40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using Mono.Addins;
43 44
44/***************************************************** 45/*****************************************************
45 * 46 *
@@ -76,7 +77,8 @@ using OpenSim.Region.Framework.Scenes;
76 77
77namespace OpenSim.Region.CoreModules.Scripting.XMLRPC 78namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
78{ 79{
79 public class XMLRPCModule : IRegionModule, IXMLRPC 80 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XMLRPCModule")]
81 public class XMLRPCModule : ISharedRegionModule, IXMLRPC
80 { 82 {
81 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 83 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
82 84
@@ -86,6 +88,10 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
86 private Dictionary<UUID, RPCChannelInfo> m_openChannels; 88 private Dictionary<UUID, RPCChannelInfo> m_openChannels;
87 private Dictionary<UUID, SendRemoteDataRequest> m_pendingSRDResponses; 89 private Dictionary<UUID, SendRemoteDataRequest> m_pendingSRDResponses;
88 private int m_remoteDataPort = 0; 90 private int m_remoteDataPort = 0;
91 public int Port
92 {
93 get { return m_remoteDataPort; }
94 }
89 95
90 private Dictionary<UUID, RPCRequestInfo> m_rpcPending; 96 private Dictionary<UUID, RPCRequestInfo> m_rpcPending;
91 private Dictionary<UUID, RPCRequestInfo> m_rpcPendingResponses; 97 private Dictionary<UUID, RPCRequestInfo> m_rpcPendingResponses;
@@ -94,34 +100,24 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
94 private int RemoteReplyScriptWait = 300; 100 private int RemoteReplyScriptWait = 300;
95 private object XMLRPCListLock = new object(); 101 private object XMLRPCListLock = new object();
96 102
97 #region IRegionModule Members 103 #region ISharedRegionModule Members
98 104
99 public void Initialise(Scene scene, IConfigSource config) 105 public void Initialise(IConfigSource config)
100 { 106 {
101 // We need to create these early because the scripts might be calling 107 // We need to create these early because the scripts might be calling
102 // But since this gets called for every region, we need to make sure they 108 // But since this gets called for every region, we need to make sure they
103 // get called only one time (or we lose any open channels) 109 // get called only one time (or we lose any open channels)
104 if (null == m_openChannels) 110 m_openChannels = new Dictionary<UUID, RPCChannelInfo>();
105 { 111 m_rpcPending = new Dictionary<UUID, RPCRequestInfo>();
106 m_openChannels = new Dictionary<UUID, RPCChannelInfo>(); 112 m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
107 m_rpcPending = new Dictionary<UUID, RPCRequestInfo>(); 113 m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
108 m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
109 m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
110 114
111 try 115 try
112 { 116 {
113 m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort); 117 m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
114 }
115 catch (Exception)
116 {
117 }
118 } 118 }
119 119 catch (Exception)
120 if (!m_scenes.Contains(scene))
121 { 120 {
122 m_scenes.Add(scene);
123
124 scene.RegisterModuleInterface<IXMLRPC>(this);
125 } 121 }
126 } 122 }
127 123
@@ -131,32 +127,56 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
131 { 127 {
132 // Start http server 128 // Start http server
133 // Attach xmlrpc handlers 129 // Attach xmlrpc handlers
134// m_log.InfoFormat( 130 // m_log.InfoFormat(
135// "[XML RPC MODULE]: Starting up XMLRPC Server on port {0} for llRemoteData commands.", 131 // "[XML RPC MODULE]: Starting up XMLRPC Server on port {0} for llRemoteData commands.",
136// m_remoteDataPort); 132 // m_remoteDataPort);
137 133
138 IHttpServer httpServer = MainServer.GetHttpServer((uint)m_remoteDataPort); 134 IHttpServer httpServer = MainServer.GetHttpServer((uint)m_remoteDataPort);
139 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); 135 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
140 } 136 }
141 } 137 }
142 138
143 public void Close() 139 public void AddRegion(Scene scene)
140 {
141 if (!IsEnabled())
142 return;
143
144 if (!m_scenes.Contains(scene))
145 {
146 m_scenes.Add(scene);
147
148 scene.RegisterModuleInterface<IXMLRPC>(this);
149 }
150 }
151
152 public void RegionLoaded(Scene scene)
144 { 153 {
145 } 154 }
146 155
147 public string Name 156 public void RemoveRegion(Scene scene)
148 { 157 {
149 get { return m_name; } 158 if (!IsEnabled())
159 return;
160
161 if (m_scenes.Contains(scene))
162 {
163 scene.UnregisterModuleInterface<IXMLRPC>(this);
164 m_scenes.Remove(scene);
165 }
150 } 166 }
151 167
152 public bool IsSharedModule 168 public void Close()
153 { 169 {
154 get { return true; }
155 } 170 }
156 171
157 public int Port 172 public string Name
158 { 173 {
159 get { return m_remoteDataPort; } 174 get { return m_name; }
175 }
176
177 public Type ReplaceableInterface
178 {
179 get { return null; }
160 } 180 }
161 181
162 #endregion 182 #endregion