diff options
Diffstat (limited to '')
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.Reflection; | ||
32 | using System.Threading; | ||
33 | using log4net.Config; | ||
34 | using Nini.Config; | ||
35 | using NUnit.Framework; | ||
36 | using OpenMetaverse; | ||
37 | using OpenMetaverse.Assets; | ||
38 | using Flotsam.RegionModules.AssetCache; | ||
39 | using OpenSim.Framework; | ||
40 | using OpenSim.Region.Framework.Scenes; | ||
41 | using OpenSim.Region.Framework.Scenes.Serialization; | ||
42 | using OpenSim.Tests.Common; | ||
43 | using OpenSim.Tests.Common.Mock; | ||
44 | |||
45 | namespace 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 @@ | |||
28 | using OpenMetaverse; | 28 | using OpenMetaverse; |
29 | using OpenSim.Region.Framework.Scenes; | 29 | using OpenSim.Region.Framework.Scenes; |
30 | 30 | ||
31 | namespace OpenSim.Region.CoreModules.Avatar.NPC | 31 | namespace 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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using System.Threading; | ||
32 | using log4net; | ||
33 | using OpenMetaverse; | ||
34 | using OpenSim.Framework; | ||
35 | using OpenSim.Region.Framework.Interfaces; | ||
36 | |||
37 | namespace 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; | |||
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using OpenSim.Region.Framework.Interfaces; | 35 | using OpenSim.Region.Framework.Interfaces; |
36 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
37 | using OpenSim.Region.CoreModules.Avatar.NPC; | ||
38 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
39 | using Timer=System.Timers.Timer; | 38 | using Timer=System.Timers.Timer; |
40 | using OpenSim.Services.Interfaces; | 39 | using 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 | |||
28 | using System; | ||
29 | using System.Reflection; | ||
30 | using Nini.Config; | ||
31 | using NUnit.Framework; | ||
32 | using OpenMetaverse; | ||
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Framework.Communications; | ||
35 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar; | ||
36 | using OpenSim.Region.Framework.Interfaces; | ||
37 | using OpenSim.Region.Framework.Scenes; | ||
38 | using OpenSim.Services.AvatarService; | ||
39 | using OpenSim.Tests.Common; | ||
40 | using OpenSim.Tests.Common.Mock; | ||
41 | |||
42 | namespace 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; | |||
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | 39 | ||
40 | using OpenSim.Framework.Console; | 40 | using OpenSim.Framework.Console; |
41 | using OpenSim.Region.CoreModules.Avatar.NPC; | ||
42 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
43 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
44 | using OpenSim.Region.ScriptEngine.Shared; | 43 | using OpenSim.Region.ScriptEngine.Shared; |