aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs267
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs127
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs (renamed from OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs)2
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs156
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs8
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs142
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs71
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs21
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs1
15 files changed, 597 insertions, 245 deletions
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index 2d81ea8..d19852b 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -328,7 +328,7 @@ namespace OpenSim
328 config.Set("meshing", "Meshmerizer"); 328 config.Set("meshing", "Meshmerizer");
329 config.Set("physical_prim", true); 329 config.Set("physical_prim", true);
330 config.Set("see_into_this_sim_from_neighbor", true); 330 config.Set("see_into_this_sim_from_neighbor", true);
331 config.Set("serverside_object_permissions", false); 331 config.Set("serverside_object_permissions", true);
332 config.Set("storage_plugin", "OpenSim.Data.SQLite.dll"); 332 config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
333 config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3"); 333 config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
334 config.Set("storage_prim_inventories", true); 334 config.Set("storage_prim_inventories", true);
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 9ef5bc9..d85d727 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -86,6 +86,8 @@ namespace Flotsam.RegionModules.AssetCache
86 private List<string> m_CurrentlyWriting = new List<string>(); 86 private List<string> m_CurrentlyWriting = new List<string>();
87#endif 87#endif
88 88
89 private bool m_FileCacheEnabled = true;
90
89 private ExpiringCache<string, AssetBase> m_MemoryCache; 91 private ExpiringCache<string, AssetBase> m_MemoryCache;
90 private bool m_MemoryCacheEnabled = false; 92 private bool m_MemoryCacheEnabled = false;
91 93
@@ -146,6 +148,7 @@ namespace Flotsam.RegionModules.AssetCache
146 } 148 }
147 else 149 else
148 { 150 {
151 m_FileCacheEnabled = assetConfig.GetBoolean("FileCacheEnabled", m_FileCacheEnabled);
149 m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); 152 m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory);
150 153
151 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); 154 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
@@ -173,7 +176,7 @@ namespace Flotsam.RegionModules.AssetCache
173 176
174 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); 177 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
175 178
176 if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) 179 if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
177 { 180 {
178 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds); 181 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
179 m_CacheCleanTimer.AutoReset = true; 182 m_CacheCleanTimer.AutoReset = true;
@@ -226,7 +229,6 @@ namespace Flotsam.RegionModules.AssetCache
226 if (m_AssetService == null) 229 if (m_AssetService == null)
227 { 230 {
228 m_AssetService = scene.RequestModuleInterface<IAssetService>(); 231 m_AssetService = scene.RequestModuleInterface<IAssetService>();
229
230 } 232 }
231 } 233 }
232 } 234 }
@@ -250,18 +252,15 @@ namespace Flotsam.RegionModules.AssetCache
250 252
251 private void UpdateMemoryCache(string key, AssetBase asset) 253 private void UpdateMemoryCache(string key, AssetBase asset)
252 { 254 {
253 if (m_MemoryCacheEnabled) 255 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
254 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
255 } 256 }
256 257
257 public void Cache(AssetBase asset) 258 private void UpdateFileCache(string key, AssetBase asset)
258 { 259 {
259 // TODO: Spawn this off to some seperate thread to do the actual writing 260 // TODO: Spawn this off to some seperate thread to do the actual writing
260 if (asset != null) 261 if (asset != null)
261 { 262 {
262 UpdateMemoryCache(asset.ID, asset); 263 string filename = GetFileName(key);
263
264 string filename = GetFileName(asset.ID);
265 264
266 try 265 try
267 { 266 {
@@ -278,8 +277,8 @@ namespace Flotsam.RegionModules.AssetCache
278 catch 277 catch
279 { 278 {
280 } 279 }
281 } else { 280 } else {
282 281
283 // Once we start writing, make sure we flag that we're writing 282 // Once we start writing, make sure we flag that we're writing
284 // that object to the cache so that we don't try to write the 283 // that object to the cache so that we don't try to write the
285 // same file multiple times. 284 // same file multiple times.
@@ -319,78 +318,118 @@ namespace Flotsam.RegionModules.AssetCache
319 } 318 }
320 } 319 }
321 320
322 public AssetBase Get(string id) 321 public void Cache(AssetBase asset)
323 { 322 {
324 m_Requests++; 323 // TODO: Spawn this off to some seperate thread to do the actual writing
324 if (asset != null)
325 {
326 //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
327
328 if (m_MemoryCacheEnabled)
329 UpdateMemoryCache(asset.ID, asset);
330
331 if (m_FileCacheEnabled)
332 UpdateFileCache(asset.ID, asset);
333 }
334 }
325 335
336 /// <summary>
337 /// Try to get an asset from the in-memory cache.
338 /// </summary>
339 /// <param name="id"></param>
340 /// <returns></returns>
341 private AssetBase GetFromMemoryCache(string id)
342 {
326 AssetBase asset = null; 343 AssetBase asset = null;
327 344
328 if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset)) 345 if (m_MemoryCache.TryGetValue(id, out asset))
329 {
330 m_MemoryHits++; 346 m_MemoryHits++;
331 } 347
332 else 348 return asset;
349 }
350
351 /// <summary>
352 /// Try to get an asset from the file cache.
353 /// </summary>
354 /// <param name="id"></param>
355 /// <returns></returns>
356 private AssetBase GetFromFileCache(string id)
357 {
358 AssetBase asset = null;
359
360 string filename = GetFileName(id);
361 if (File.Exists(filename))
333 { 362 {
334 string filename = GetFileName(id); 363 FileStream stream = null;
335 if (File.Exists(filename)) 364 try
336 { 365 {
337 FileStream stream = null; 366 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
338 try 367 BinaryFormatter bformatter = new BinaryFormatter();
339 {
340 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
341 BinaryFormatter bformatter = new BinaryFormatter();
342 368
343 asset = (AssetBase)bformatter.Deserialize(stream); 369 asset = (AssetBase)bformatter.Deserialize(stream);
344 370
345 UpdateMemoryCache(id, asset); 371 UpdateMemoryCache(id, asset);
346 372
347 m_DiskHits++; 373 m_DiskHits++;
348 } 374 }
349 catch (System.Runtime.Serialization.SerializationException e) 375 catch (System.Runtime.Serialization.SerializationException e)
350 { 376 {
351 LogException(e); 377 LogException(e);
352 378
353 // If there was a problem deserializing the asset, the asset may 379 // If there was a problem deserializing the asset, the asset may
354 // either be corrupted OR was serialized under an old format 380 // either be corrupted OR was serialized under an old format
355 // {different version of AssetBase} -- we should attempt to 381 // {different version of AssetBase} -- we should attempt to
356 // delete it and re-cache 382 // delete it and re-cache
357 File.Delete(filename); 383 File.Delete(filename);
358 } 384 }
359 catch (Exception e) 385 catch (Exception e)
360 { 386 {
361 LogException(e); 387 LogException(e);
362 }
363 finally
364 {
365 if (stream != null)
366 stream.Close();
367 }
368 } 388 }
389 finally
390 {
391 if (stream != null)
392 stream.Close();
393 }
394 }
369 395
370 396
371#if WAIT_ON_INPROGRESS_REQUESTS 397#if WAIT_ON_INPROGRESS_REQUESTS
372 // Check if we're already downloading this asset. If so, try to wait for it to 398 // Check if we're already downloading this asset. If so, try to wait for it to
373 // download. 399 // download.
374 if (m_WaitOnInprogressTimeout > 0) 400 if (m_WaitOnInprogressTimeout > 0)
375 { 401 {
376 m_RequestsForInprogress++; 402 m_RequestsForInprogress++;
377 403
378 ManualResetEvent waitEvent; 404 ManualResetEvent waitEvent;
379 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) 405 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
380 {
381 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
382 return Get(id);
383 }
384 }
385#else
386 // Track how often we have the problem that an asset is requested while
387 // it is still being downloaded by a previous request.
388 if (m_CurrentlyWriting.Contains(filename))
389 { 406 {
390 m_RequestsForInprogress++; 407 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
408 return Get(id);
391 } 409 }
392#endif
393 } 410 }
411#else
412 // Track how often we have the problem that an asset is requested while
413 // it is still being downloaded by a previous request.
414 if (m_CurrentlyWriting.Contains(filename))
415 {
416 m_RequestsForInprogress++;
417 }
418#endif
419
420 return asset;
421 }
422
423 public AssetBase Get(string id)
424 {
425 m_Requests++;
426
427 AssetBase asset = null;
428
429 if (m_MemoryCacheEnabled)
430 asset = GetFromMemoryCache(id);
431 else if (m_FileCacheEnabled)
432 asset = GetFromFileCache(id);
394 433
395 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 434 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
396 { 435 {
@@ -424,10 +463,13 @@ namespace Flotsam.RegionModules.AssetCache
424 463
425 try 464 try
426 { 465 {
427 string filename = GetFileName(id); 466 if (m_FileCacheEnabled)
428 if (File.Exists(filename))
429 { 467 {
430 File.Delete(filename); 468 string filename = GetFileName(id);
469 if (File.Exists(filename))
470 {
471 File.Delete(filename);
472 }
431 } 473 }
432 474
433 if (m_MemoryCacheEnabled) 475 if (m_MemoryCacheEnabled)
@@ -442,11 +484,14 @@ namespace Flotsam.RegionModules.AssetCache
442 public void Clear() 484 public void Clear()
443 { 485 {
444 if (m_LogLevel >= 2) 486 if (m_LogLevel >= 2)
445 m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing Cache."); 487 m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches.");
446 488
447 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 489 if (m_FileCacheEnabled)
448 { 490 {
449 Directory.Delete(dir); 491 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
492 {
493 Directory.Delete(dir);
494 }
450 } 495 }
451 496
452 if (m_MemoryCacheEnabled) 497 if (m_MemoryCacheEnabled)
@@ -481,9 +526,9 @@ namespace Flotsam.RegionModules.AssetCache
481 /// removes empty tier directories. 526 /// removes empty tier directories.
482 /// </summary> 527 /// </summary>
483 /// <param name="dir"></param> 528 /// <param name="dir"></param>
529 /// <param name="purgeLine"></param>
484 private void CleanExpiredFiles(string dir, DateTime purgeLine) 530 private void CleanExpiredFiles(string dir, DateTime purgeLine)
485 { 531 {
486
487 foreach (string file in Directory.GetFiles(dir)) 532 foreach (string file in Directory.GetFiles(dir))
488 { 533 {
489 if (File.GetLastAccessTime(file) < purgeLine) 534 if (File.GetLastAccessTime(file) < purgeLine)
@@ -721,18 +766,28 @@ namespace Flotsam.RegionModules.AssetCache
721 switch (cmd) 766 switch (cmd)
722 { 767 {
723 case "status": 768 case "status":
724 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache : {0} assets", m_MemoryCache.Count); 769 if (m_MemoryCacheEnabled)
725 770 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count);
726 int fileCount = GetFileCacheCount(m_CacheDirectory); 771 else
727 m_log.InfoFormat("[FLOTSAM ASSET CACHE] File Cache : {0} assets", fileCount); 772 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled");
728 773
729 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 774 if (m_FileCacheEnabled)
730 { 775 {
731 m_log.Info("[FLOTSAM ASSET CACHE] Deep Scans were performed on the following regions:"); 776 int fileCount = GetFileCacheCount(m_CacheDirectory);
732 777 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount);
733 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 778
734 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 779 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
735 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 780 {
781 m_log.Info("[FLOTSAM ASSET CACHE]: Deep Scans were performed on the following regions:");
782
783 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
784 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
785 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
786 }
787 }
788 else
789 {
790 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
736 } 791 }
737 792
738 break; 793 break;
@@ -740,7 +795,7 @@ namespace Flotsam.RegionModules.AssetCache
740 case "clear": 795 case "clear":
741 if (cmdparams.Length < 2) 796 if (cmdparams.Length < 2)
742 { 797 {
743 m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]"); 798 m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]");
744 break; 799 break;
745 } 800 }
746 801
@@ -761,36 +816,48 @@ namespace Flotsam.RegionModules.AssetCache
761 816
762 if (clearMemory) 817 if (clearMemory)
763 { 818 {
764 m_MemoryCache.Clear(); 819 if (m_MemoryCacheEnabled)
765 m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); 820 {
821 m_MemoryCache.Clear();
822 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared.");
823 }
824 else
825 {
826 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled.");
827 }
766 } 828 }
767 829
768 if (clearFile) 830 if (clearFile)
769 { 831 {
770 ClearFileCache(); 832 if (m_FileCacheEnabled)
771 m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); 833 {
834 ClearFileCache();
835 m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared.");
836 }
837 else
838 {
839 m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled.");
840 }
772 } 841 }
773 842
774 break; 843 break;
775 844
776 845
777 case "assets": 846 case "assets":
778 m_log.Info("[FLOTSAM ASSET CACHE] Caching all assets, in all scenes."); 847 m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
779 848
780 Util.FireAndForget(delegate { 849 Util.FireAndForget(delegate {
781 int assetsCached = CacheScenes(); 850 int assetsCached = CacheScenes();
782 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Completed Scene Caching, {0} assets found.", assetsCached); 851 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
783 852
784 }); 853 });
785 854
786 break; 855 break;
787 856
788 case "expire": 857 case "expire":
789
790
791 if (cmdparams.Length < 3) 858 if (cmdparams.Length < 3)
792 { 859 {
793 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Invalid parameters for Expire, please specify a valid date & time", cmd); 860 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd);
794 break; 861 break;
795 } 862 }
796 863
@@ -808,26 +875,28 @@ namespace Flotsam.RegionModules.AssetCache
808 875
809 if (!DateTime.TryParse(s_expirationDate, out expirationDate)) 876 if (!DateTime.TryParse(s_expirationDate, out expirationDate))
810 { 877 {
811 m_log.InfoFormat("[FLOTSAM ASSET CACHE] {0} is not a valid date & time", cmd); 878 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd);
812 break; 879 break;
813 } 880 }
814 881
815 CleanExpiredFiles(m_CacheDirectory, expirationDate); 882 if (m_FileCacheEnabled)
883 CleanExpiredFiles(m_CacheDirectory, expirationDate);
884 else
885 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing.");
816 886
817 break; 887 break;
818 default: 888 default:
819 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Unknown command {0}", cmd); 889 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd);
820 break; 890 break;
821 } 891 }
822 } 892 }
823 else if (cmdparams.Length == 1) 893 else if (cmdparams.Length == 1)
824 { 894 {
825 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache status - Display cache status"); 895 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status");
826 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearmem - Remove all assets cached in memory"); 896 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory");
827 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearfile - Remove all assets cached on disk"); 897 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk");
828 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache cachescenes - Attempt a deep cache of all assets in all scenes"); 898 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes");
829 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache <datetime> - Purge assets older then the specified date & time"); 899 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
830
831 } 900 }
832 } 901 }
833 902
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
new file mode 100644
index 0000000..63b0c31
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -0,0 +1,127 @@
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.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Threading;
33using log4net.Config;
34using Nini.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenMetaverse.Assets;
38using Flotsam.RegionModules.AssetCache;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Scenes.Serialization;
42using OpenSim.Tests.Common;
43using OpenSim.Tests.Common.Mock;
44
45namespace OpenSim.Region.CoreModules.Asset.Tests
46{
47 /// <summary>
48 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness.
49 /// </summary>
50 [TestFixture]
51 public class FlotsamAssetCacheTests
52 {
53 protected TestScene m_scene;
54 protected FlotsamAssetCache m_cache;
55
56 [SetUp]
57 public void SetUp()
58 {
59 IConfigSource config = new IniConfigSource();
60
61 config.AddConfig("Modules");
62 config.Configs["Modules"].Set("AssetCaching", "FlotsamAssetCache");
63 config.AddConfig("AssetCache");
64 config.Configs["AssetCache"].Set("FileCacheEnabled", "false");
65 config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true");
66
67 m_cache = new FlotsamAssetCache();
68 m_scene = SceneSetupHelpers.SetupScene();
69 SceneSetupHelpers.SetupSceneModules(m_scene, config, m_cache);
70 }
71
72 [Test]
73 public void TestCacheAsset()
74 {
75 TestHelper.InMethod();
76// log4net.Config.XmlConfigurator.Configure();
77
78 AssetBase asset = AssetHelpers.CreateAsset();
79 asset.ID = TestHelper.ParseTail(0x1).ToString();
80
81 // Check we don't get anything before the asset is put in the cache
82 AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
83 Assert.That(retrievedAsset, Is.Null);
84
85 m_cache.Store(asset);
86
87 // Check that asset is now in cache
88 retrievedAsset = m_cache.Get(asset.ID.ToString());
89 Assert.That(retrievedAsset, Is.Not.Null);
90 Assert.That(retrievedAsset.ID, Is.EqualTo(asset.ID));
91 }
92
93 [Test]
94 public void TestExpireAsset()
95 {
96 TestHelper.InMethod();
97// log4net.Config.XmlConfigurator.Configure();
98
99 AssetBase asset = AssetHelpers.CreateAsset();
100 asset.ID = TestHelper.ParseTail(0x2).ToString();
101
102 m_cache.Store(asset);
103
104 m_cache.Expire(asset.ID);
105
106 AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
107 Assert.That(retrievedAsset, Is.Null);
108 }
109
110 [Test]
111 public void TestClearCache()
112 {
113 TestHelper.InMethod();
114// log4net.Config.XmlConfigurator.Configure();
115
116 AssetBase asset = AssetHelpers.CreateAsset();
117 asset.ID = TestHelper.ParseTail(0x2).ToString();
118
119 m_cache.Store(asset);
120
121 m_cache.Clear();
122
123 AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
124 Assert.That(retrievedAsset, Is.Null);
125 }
126 }
127} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 2a6d362..04b20d4 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -449,7 +449,7 @@ namespace OpenSim.Region.CoreModules.World.Land
449 449
450 public bool IsBannedFromLand(UUID avatar) 450 public bool IsBannedFromLand(UUID avatar)
451 { 451 {
452 if (m_scene.Permissions.IsAdministrator(avatar)) 452 if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
453 return false; 453 return false;
454 454
455 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) 455 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
@@ -463,7 +463,7 @@ namespace OpenSim.Region.CoreModules.World.Land
463 if (e.AgentID == avatar && e.Flags == AccessList.Ban) 463 if (e.AgentID == avatar && e.Flags == AccessList.Ban)
464 return true; 464 return true;
465 return false; 465 return false;
466 }) != -1 && LandData.OwnerID != avatar) 466 }) != -1)
467 { 467 {
468 return true; 468 return true;
469 } 469 }
@@ -473,7 +473,7 @@ namespace OpenSim.Region.CoreModules.World.Land
473 473
474 public bool IsRestrictedFromLand(UUID avatar) 474 public bool IsRestrictedFromLand(UUID avatar)
475 { 475 {
476 if (m_scene.Permissions.IsAdministrator(avatar)) 476 if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
477 return false; 477 return false;
478 478
479 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) 479 if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
@@ -487,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Land
487 if (e.AgentID == avatar && e.Flags == AccessList.Access) 487 if (e.AgentID == avatar && e.Flags == AccessList.Access)
488 return true; 488 return true;
489 return false; 489 return false;
490 }) == -1 && LandData.OwnerID != avatar) 490 }) == -1)
491 { 491 {
492 if (!HasGroupAccess(avatar)) 492 if (!HasGroupAccess(avatar))
493 { 493 {
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 43b37c7..2c7843f 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -134,7 +134,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
134 return; 134 return;
135 135
136 m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false); 136 m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false);
137 m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", false); 137 m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true);
138 m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true); 138 m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true);
139 m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true); 139 m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true);
140 m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false); 140 m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false);
diff --git a/OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index cd2fe4f..21a755f 100644
--- a/OpenSim/Region/CoreModules/Avatar/NPC/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -28,7 +28,7 @@
28using OpenMetaverse; 28using OpenMetaverse;
29using OpenSim.Region.Framework.Scenes; 29using OpenSim.Region.Framework.Scenes;
30 30
31namespace OpenSim.Region.CoreModules.Avatar.NPC 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface INPCModule 33 public interface INPCModule
34 { 34 {
diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
new file mode 100644
index 0000000..06cd14b
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
@@ -0,0 +1,156 @@
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.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36
37namespace OpenSim.Region.Framework.Scenes
38{
39 class FetchHolder
40 {
41 public IClientAPI Client { get; private set; }
42 public UUID ItemID { get; private set; }
43
44 public FetchHolder(IClientAPI client, UUID itemID)
45 {
46 Client = client;
47 ItemID = itemID;
48 }
49 }
50
51 /// <summary>
52 /// Send FetchInventoryReply information to clients asynchronously on a single thread rather than asynchronously via
53 /// multiple threads.
54 /// </summary>
55 /// <remarks>
56 /// If the main root inventory is right-clicked on a version 1 viewer for a user with a large inventory, a very
57 /// very large number of FetchInventory requests are sent to the simulator. Each is handled on a separate thread
58 /// by the IClientAPI, but the sheer number of requests overwhelms the number of threads available and ends up
59 /// freezing the inbound packet handling.
60 ///
61 /// This class makes the first FetchInventory packet thread process the queue. If new requests come
62 /// in while it is processing, then the subsequent threads just add the requests and leave it to the original
63 /// thread to process them.
64 ///
65 /// This might slow down outbound packets but these are limited by the IClientAPI outbound queues
66 /// anyway.
67 ///
68 /// It might be possible to ignore FetchInventory requests altogether, particularly as they are redundant wrt to
69 /// FetchInventoryDescendents requests, but this would require more investigation.
70 /// </remarks>
71 public class AsyncInventorySender
72 {
73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74
75 protected Scene m_scene;
76
77 /// <summary>
78 /// Queues fetch requests
79 /// </summary>
80 Queue<FetchHolder> m_fetchHolder = new Queue<FetchHolder>();
81
82 /// <summary>
83 /// Signal whether a queue is currently being processed or not.
84 /// </summary>
85 protected volatile bool m_processing;
86
87 public AsyncInventorySender(Scene scene)
88 {
89 m_processing = false;
90 m_scene = scene;
91 }
92
93 /// <summary>
94 /// Handle a fetch inventory request from the client
95 /// </summary>
96 /// <param name="remoteClient"></param>
97 /// <param name="itemID"></param>
98 /// <param name="ownerID"></param>
99 public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
100 {
101 lock (m_fetchHolder)
102 {
103// m_log.DebugFormat(
104// "[ASYNC INVENTORY SENDER]: Putting request from {0} for {1} on queue", remoteClient.Name, itemID);
105
106 m_fetchHolder.Enqueue(new FetchHolder(remoteClient, itemID));
107 }
108
109 if (!m_processing)
110 {
111 m_processing = true;
112 ProcessQueue();
113 }
114 }
115
116 /// <summary>
117 /// Process the queue of fetches
118 /// </summary>
119 protected void ProcessQueue()
120 {
121 FetchHolder fh = null;
122
123 while (true)
124 {
125 lock (m_fetchHolder)
126 {
127// m_log.DebugFormat("[ASYNC INVENTORY SENDER]: {0} items left to process", m_fetchHolder.Count);
128
129 if (m_fetchHolder.Count == 0)
130 {
131 m_processing = false;
132 return;
133 }
134 else
135 {
136 fh = m_fetchHolder.Dequeue();
137 }
138 }
139
140 if (fh.Client.IsLoggingOut)
141 continue;
142
143// m_log.DebugFormat(
144// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID);
145
146 InventoryItemBase item = new InventoryItemBase(fh.ItemID, fh.Client.AgentId);
147 item = m_scene.InventoryService.GetItem(item);
148
149 if (item != null)
150 fh.Client.SendInventoryItemDetails(item.Owner, item);
151
152 // TODO: Possibly log any failure
153 }
154 }
155 }
156} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 28c0276..dbefb4a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -52,6 +52,11 @@ namespace OpenSim.Region.Framework.Scenes
52 protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter; 52 protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;
53 53
54 /// <summary> 54 /// <summary>
55 /// Allows inventory details to be sent to clients asynchronously
56 /// </summary>
57 protected AsyncInventorySender m_asyncInventorySender;
58
59 /// <summary>
55 /// Start all the scripts in the scene which should be started. 60 /// Start all the scripts in the scene which should be started.
56 /// </summary> 61 /// </summary>
57 public void CreateScriptInstances() 62 public void CreateScriptInstances()
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e2d7208..44472b2 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -461,31 +461,6 @@ namespace OpenSim.Region.Framework.Scenes
461 } 461 }
462 ); 462 );
463 } 463 }
464
465
466 /// <summary>
467 /// Handle a fetch inventory request from the client
468 /// </summary>
469 /// <param name="remoteClient"></param>
470 /// <param name="itemID"></param>
471 /// <param name="ownerID"></param>
472 public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
473 {
474 if (LibraryService != null && LibraryService.LibraryRootFolder != null && ownerID == LibraryService.LibraryRootFolder.Owner)
475 {
476 //m_log.Debug("request info for library item");
477 return;
478 }
479
480 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
481 item = InventoryService.GetItem(item);
482
483 if (item != null)
484 {
485 remoteClient.SendInventoryItemDetails(ownerID, item);
486 }
487 // else shouldn't we send an alert message?
488 }
489 464
490 /// <summary> 465 /// <summary>
491 /// Tell the client about the various child items and folders contained in the requested folder. 466 /// Tell the client about the various child items and folders contained in the requested folder.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 253adae..e02a866 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -604,6 +604,8 @@ namespace OpenSim.Region.Framework.Scenes
604 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 604 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
605 m_asyncSceneObjectDeleter.Enabled = true; 605 m_asyncSceneObjectDeleter.Enabled = true;
606 606
607 m_asyncInventorySender = new AsyncInventorySender(this);
608
607 #region Region Settings 609 #region Region Settings
608 610
609 // Load region settings 611 // Load region settings
@@ -2866,14 +2868,13 @@ namespace OpenSim.Region.Framework.Scenes
2866 2868
2867 public virtual void SubscribeToClientInventoryEvents(IClientAPI client) 2869 public virtual void SubscribeToClientInventoryEvents(IClientAPI client)
2868 { 2870 {
2869
2870 client.OnLinkInventoryItem += HandleLinkInventoryItem; 2871 client.OnLinkInventoryItem += HandleLinkInventoryItem;
2871 client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; 2872 client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder;
2872 client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; 2873 client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder;
2873 client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!! 2874 client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!!
2874 client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents; 2875 client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents;
2875 client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!! 2876 client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!!
2876 client.OnFetchInventory += HandleFetchInventory; 2877 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2877 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2878 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2878 client.OnCopyInventoryItem += CopyInventoryItem; 2879 client.OnCopyInventoryItem += CopyInventoryItem;
2879 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy; 2880 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
@@ -2993,13 +2994,12 @@ namespace OpenSim.Region.Framework.Scenes
2993 2994
2994 public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) 2995 public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client)
2995 { 2996 {
2996
2997 client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; 2997 client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder;
2998 client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; 2998 client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder;
2999 client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! 2999 client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!!
3000 client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; 3000 client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents;
3001 client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! 3001 client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!!
3002 client.OnFetchInventory -= HandleFetchInventory; 3002 client.OnFetchInventory -= m_asyncInventorySender.HandleFetchInventory;
3003 client.OnUpdateInventoryItem -= UpdateInventoryItemAsset; 3003 client.OnUpdateInventoryItem -= UpdateInventoryItemAsset;
3004 client.OnCopyInventoryItem -= CopyInventoryItem; 3004 client.OnCopyInventoryItem -= CopyInventoryItem;
3005 client.OnMoveInventoryItem -= MoveInventoryItem; 3005 client.OnMoveInventoryItem -= MoveInventoryItem;
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 48d236f..3cdd06d 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -34,7 +34,6 @@ using Nini.Config;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.CoreModules.Avatar.NPC;
38using OpenSim.Framework; 37using OpenSim.Framework;
39using Timer=System.Timers.Timer; 38using Timer=System.Timers.Timer;
40using OpenSim.Services.Interfaces; 39using OpenSim.Services.Interfaces;
@@ -47,31 +46,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
47 46
48 // private const bool m_enabled = false; 47 // private const bool m_enabled = false;
49 48
50 private Mutex m_createMutex;
51 private Timer m_timer;
52
53 private Dictionary<UUID,NPCAvatar> m_avatars = new Dictionary<UUID, NPCAvatar>(); 49 private Dictionary<UUID,NPCAvatar> m_avatars = new Dictionary<UUID, NPCAvatar>();
54 private Dictionary<UUID,AvatarAppearance> m_appearanceCache = new Dictionary<UUID, AvatarAppearance>(); 50 private Dictionary<UUID,AvatarAppearance> m_appearanceCache = new Dictionary<UUID, AvatarAppearance>();
55 51
56 // Timer vars.
57 private bool p_inUse = false;
58 private readonly object p_lock = new object();
59 // Private Temporary Variables.
60 private string p_firstname;
61 private string p_lastname;
62 private Vector3 p_position;
63 private Scene p_scene;
64 private UUID p_cloneAppearanceFrom;
65 private UUID p_returnUuid;
66
67 public void Initialise(Scene scene, IConfigSource source) 52 public void Initialise(Scene scene, IConfigSource source)
68 { 53 {
69 m_createMutex = new Mutex(false);
70
71 m_timer = new Timer(500);
72 m_timer.Elapsed += m_timer_Elapsed;
73 m_timer.Start();
74
75 scene.RegisterModuleInterface<INPCModule>(this); 54 scene.RegisterModuleInterface<INPCModule>(this);
76 } 55 }
77 56
@@ -90,35 +69,53 @@ namespace OpenSim.Region.OptionalModules.World.NPC
90 return new AvatarAppearance(); 69 return new AvatarAppearance();
91 } 70 }
92 71
93 public UUID CreateNPC(string firstname, string lastname,Vector3 position, Scene scene, UUID cloneAppearanceFrom) 72 public UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, UUID cloneAppearanceFrom)
94 { 73 {
74 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene);
75 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue);
76
95 m_log.DebugFormat( 77 m_log.DebugFormat(
96 "[NPC MODULE]: Queueing request to create NPC {0} {1} at {2} in {3} cloning appearance of {4}", 78 "[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}",
97 firstname, lastname, position, scene.RegionInfo.RegionName, cloneAppearanceFrom); 79 firstname, lastname, npcAvatar.AgentId, position, scene.RegionInfo.RegionName);
80
81 AgentCircuitData acd = new AgentCircuitData();
82 acd.AgentID = npcAvatar.AgentId;
83 acd.firstname = firstname;
84 acd.lastname = lastname;
85 acd.ServiceURLs = new Dictionary<string, object>();
98 86
99 // Block. 87 AvatarAppearance originalAppearance = GetAppearance(cloneAppearanceFrom, scene);
100 m_createMutex.WaitOne(); 88 AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true);
89 acd.Appearance = npcAppearance;
101 90
102 // Copy Temp Variables for Timer to pick up. 91 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
103 lock (p_lock) 92 scene.AddNewClient(npcAvatar);
93
94 ScenePresence sp;
95 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
104 { 96 {
105 p_firstname = firstname; 97 m_log.DebugFormat(
106 p_lastname = lastname; 98 "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
107 p_position = position; 99
108 p_scene = scene; 100 // Shouldn't call this - temporary.
109 p_cloneAppearanceFrom = cloneAppearanceFrom; 101 sp.CompleteMovement(npcAvatar);
110 p_inUse = true;
111 p_returnUuid = UUID.Zero;
112 }
113 102
114 while (p_returnUuid == UUID.Zero) 103// sp.SendAppearanceToAllOtherAgents();
104//
105// // Send animations back to the avatar as well
106// sp.Animator.SendAnimPack();
107 }
108 else
115 { 109 {
116 Thread.Sleep(250); 110 m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID);
117 } 111 }
118 112
119 m_createMutex.ReleaseMutex(); 113 lock (m_avatars)
114 m_avatars.Add(npcAvatar.AgentId, npcAvatar);
120 115
121 return p_returnUuid; 116 m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId);
117
118 return npcAvatar.AgentId;
122 } 119 }
123 120
124 public void Autopilot(UUID agentID, Scene scene, Vector3 pos) 121 public void Autopilot(UUID agentID, Scene scene, Vector3 pos)
@@ -157,69 +154,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
157 } 154 }
158 } 155 }
159 156
160 void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
161 {
162 try
163 {
164 lock (p_lock)
165 {
166 if (p_inUse)
167 {
168 p_inUse = false;
169
170 NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene);
171 npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue);
172
173 m_log.DebugFormat(
174 "[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}",
175 p_firstname, p_lastname, npcAvatar.AgentId, p_position, p_scene.RegionInfo.RegionName);
176
177 AgentCircuitData acd = new AgentCircuitData();
178 acd.AgentID = npcAvatar.AgentId;
179 acd.firstname = p_firstname;
180 acd.lastname = p_lastname;
181 acd.ServiceURLs = new Dictionary<string, object>();
182
183 AvatarAppearance originalAppearance = GetAppearance(p_cloneAppearanceFrom, p_scene);
184 AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true);
185 acd.Appearance = npcAppearance;
186
187 p_scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
188 p_scene.AddNewClient(npcAvatar);
189
190 ScenePresence sp;
191 if (p_scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
192 {
193 m_log.DebugFormat(
194 "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
195
196 // Shouldn't call this - temporary.
197 sp.CompleteMovement(npcAvatar);
198
199 // sp.SendAppearanceToAllOtherAgents();
200 //
201 // // Send animations back to the avatar as well
202 // sp.Animator.SendAnimPack();
203 }
204 else
205 {
206 m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID);
207 }
208
209 m_avatars.Add(npcAvatar.AgentId, npcAvatar);
210
211 p_returnUuid = npcAvatar.AgentId;
212
213 m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", p_returnUuid);
214 }
215 }
216 }
217 catch (Exception ex)
218 {
219 m_log.ErrorFormat("[NPC MODULE]: NPC creation failed with exception {0} {1}", ex.Message, ex.StackTrace);
220 }
221 }
222
223 public void PostInitialise() 157 public void PostInitialise()
224 { 158 {
225 } 159 }
@@ -238,4 +172,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC
238 get { return true; } 172 get { return true; }
239 } 173 }
240 } 174 }
241} 175} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
new file mode 100644
index 0000000..899e721
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -0,0 +1,71 @@
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 Nini.Config;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.AvatarService;
39using OpenSim.Tests.Common;
40using OpenSim.Tests.Common.Mock;
41
42namespace OpenSim.Region.OptionalModules.World.NPC.Tests
43{
44 [TestFixture]
45 public class NPCModuleTests
46 {
47 [Test]
48 public void TestCreate()
49 {
50 TestHelper.InMethod();
51// log4net.Config.XmlConfigurator.Configure();
52
53 IConfigSource config = new IniConfigSource();
54
55 config.AddConfig("Modules");
56 config.Configs["Modules"].Set("AvatarServices", "LocalAvatarServicesConnector");
57 config.AddConfig("AvatarService");
58 config.Configs["AvatarService"].Set("LocalServiceModule", "OpenSim.Services.AvatarService.dll:AvatarService");
59 config.Configs["AvatarService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
60
61 TestScene scene = SceneSetupHelpers.SetupScene();
62 SceneSetupHelpers.SetupSceneModules(scene, config, new NPCModule(), new LocalAvatarServicesConnector());
63
64 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
65 UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, UUID.Zero);
66
67 ScenePresence npc = scene.GetScenePresence(npcId);
68 Assert.That(npc, Is.Not.Null);
69 }
70 }
71} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 99b2d84..a5fe45b 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -291,7 +291,14 @@ namespace OpenSim.Region.Physics.Meshing
291 { 291 {
292 try 292 try
293 { 293 {
294 meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data); 294 OSD osd = OSDParser.DeserializeLLSDBinary(data);
295 if (osd is OSDMap)
296 meshOsd = (OSDMap)osd;
297 else
298 {
299 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
300 return null;
301 }
295 } 302 }
296 catch (Exception e) 303 catch (Exception e)
297 { 304 {
@@ -302,11 +309,17 @@ namespace OpenSim.Region.Physics.Meshing
302 309
303 if (meshOsd is OSDMap) 310 if (meshOsd is OSDMap)
304 { 311 {
312 OSDMap physicsParms = null;
305 OSDMap map = (OSDMap)meshOsd; 313 OSDMap map = (OSDMap)meshOsd;
306 OSDMap physicsParms = (OSDMap)map["physics_shape"]; // old asset format 314 if (map.ContainsKey("physics_shape"))
307 315 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
308 if (physicsParms.Count == 0) 316 else if (map.ContainsKey("physics_mesh"))
309 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format 317 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
318 if (physicsParms == null)
319 {
320 m_log.Warn("[Mesh]: no recognized physics mesh found in mesh asset");
321 return null;
322 }
310 323
311 int physOffset = physicsParms["offset"].AsInteger() + (int)start; 324 int physOffset = physicsParms["offset"].AsInteger() + (int)start;
312 int physSize = physicsParms["size"].AsInteger(); 325 int physSize = physicsParms["size"].AsInteger();
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index a0101af..8d9f5f1 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -2502,7 +2502,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2502 } 2502 }
2503 2503
2504 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim 2504 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
2505 if (!forceSimplePrimMeshing) 2505 if (!forceSimplePrimMeshing && !pbs.SculptEntry)
2506 { 2506 {
2507 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 2507 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
2508 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 2508 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
@@ -2592,6 +2592,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2592 } 2592 }
2593 } 2593 }
2594 2594
2595 if (pbs.SculptEntry && meshSculptedPrim)
2596 iPropertiesNotSupportedDefault++;
2597
2595 2598
2596 if (iPropertiesNotSupportedDefault == 0) 2599 if (iPropertiesNotSupportedDefault == 0)
2597 { 2600 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 2b8155f..31222ff 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -38,7 +38,6 @@ using OpenSim;
38using OpenSim.Framework; 38using OpenSim.Framework;
39 39
40using OpenSim.Framework.Console; 40using OpenSim.Framework.Console;
41using OpenSim.Region.CoreModules.Avatar.NPC;
42using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.ScriptEngine.Shared; 43using OpenSim.Region.ScriptEngine.Shared;