diff options
author | Melanie | 2013-04-28 19:03:39 +0200 |
---|---|---|
committer | Melanie | 2013-04-28 19:03:39 +0200 |
commit | 4275d7a839d7380ee50aeadc38a31dd467bd891e (patch) | |
tree | 1e589fc3b448b580d1cc25b52215ef5ce2d7ae78 /OpenSim/Region/CoreModules | |
parent | Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork (diff) | |
parent | Controller module for dynamic floaters (WIP) (diff) | |
download | opensim-SC-4275d7a839d7380ee50aeadc38a31dd467bd891e.zip opensim-SC-4275d7a839d7380ee50aeadc38a31dd467bd891e.tar.gz opensim-SC-4275d7a839d7380ee50aeadc38a31dd467bd891e.tar.bz2 opensim-SC-4275d7a839d7380ee50aeadc38a31dd467bd891e.tar.xz |
Merge branch 'avination-current' of ssh://3dhosting.de/var/git/careminster into avination-current
Conflicts:
bin/Regions/Regions.ini.example
Diffstat (limited to 'OpenSim/Region/CoreModules')
75 files changed, 3473 insertions, 1414 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 7332415..f489262 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs | |||
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
42 | public class AssetTransactionModule : INonSharedRegionModule, | 42 | public class AssetTransactionModule : INonSharedRegionModule, |
43 | IAgentAssetTransactions | 43 | IAgentAssetTransactions |
44 | { | 44 | { |
45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 46 | ||
47 | protected Scene m_Scene; | 47 | protected Scene m_Scene; |
48 | private bool m_dumpAssetsToFile = false; | 48 | private bool m_dumpAssetsToFile = false; |
@@ -214,9 +214,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
214 | public void HandleTaskItemUpdateFromTransaction( | 214 | public void HandleTaskItemUpdateFromTransaction( |
215 | IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) | 215 | IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) |
216 | { | 216 | { |
217 | m_log.DebugFormat( | 217 | // m_log.DebugFormat( |
218 | "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", | 218 | // "[ASSET TRANSACTION MODULE]: Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", |
219 | item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); | 219 | // item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); |
220 | 220 | ||
221 | AgentAssetTransactions transactions = | 221 | AgentAssetTransactions transactions = |
222 | GetUserTransactions(remoteClient.AgentId); | 222 | GetUserTransactions(remoteClient.AgentId); |
@@ -230,15 +230,17 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
230 | /// </summary> | 230 | /// </summary> |
231 | /// <param name="remoteClient"></param> | 231 | /// <param name="remoteClient"></param> |
232 | /// <param name="assetID"></param> | 232 | /// <param name="assetID"></param> |
233 | /// <param name="transaction"></param> | 233 | /// <param name="transactionID"></param> |
234 | /// <param name="type"></param> | 234 | /// <param name="type"></param> |
235 | /// <param name="data"></param></param> | 235 | /// <param name="data"></param></param> |
236 | /// <param name="tempFile"></param> | 236 | /// <param name="tempFile"></param> |
237 | public void HandleUDPUploadRequest(IClientAPI remoteClient, | 237 | public void HandleUDPUploadRequest(IClientAPI remoteClient, |
238 | UUID assetID, UUID transaction, sbyte type, byte[] data, | 238 | UUID assetID, UUID transactionID, sbyte type, byte[] data, |
239 | bool storeLocal, bool tempFile) | 239 | bool storeLocal, bool tempFile) |
240 | { | 240 | { |
241 | // m_log.Debug("HandleUDPUploadRequest - assetID: " + assetID.ToString() + " transaction: " + transaction.ToString() + " type: " + type.ToString() + " storelocal: " + storeLocal + " tempFile: " + tempFile); | 241 | // m_log.DebugFormat( |
242 | // "[ASSET TRANSACTION MODULE]: HandleUDPUploadRequest - assetID: {0}, transaction {1}, type {2}, storeLocal {3}, tempFile {4}, data.Length {5}", | ||
243 | // assetID, transactionID, type, storeLocal, tempFile, data.Length); | ||
242 | 244 | ||
243 | if (((AssetType)type == AssetType.Texture || | 245 | if (((AssetType)type == AssetType.Texture || |
244 | (AssetType)type == AssetType.Sound || | 246 | (AssetType)type == AssetType.Sound || |
@@ -274,8 +276,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
274 | } | 276 | } |
275 | 277 | ||
276 | AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); | 278 | AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); |
277 | AssetXferUploader uploader = transactions.RequestXferUploader(transaction); | 279 | AssetXferUploader uploader = transactions.RequestXferUploader(transactionID); |
278 | uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); | 280 | uploader.StartUpload(remoteClient, assetID, transactionID, type, data, storeLocal, tempFile); |
279 | } | 281 | } |
280 | 282 | ||
281 | /// <summary> | 283 | /// <summary> |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 0aa4693..ffff37d 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | |||
@@ -34,6 +34,7 @@ using OpenMetaverse; | |||
34 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
35 | using OpenSim.Region.Framework.Scenes; | 35 | using OpenSim.Region.Framework.Scenes; |
36 | using OpenSim.Services.Interfaces; | 36 | using OpenSim.Services.Interfaces; |
37 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
37 | 38 | ||
38 | namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | 39 | namespace OpenSim.Region.CoreModules.Agent.AssetTransaction |
39 | { | 40 | { |
@@ -260,10 +261,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
260 | { | 261 | { |
261 | CompleteTaskItemUpdate(m_updateTaskItemData); | 262 | CompleteTaskItemUpdate(m_updateTaskItemData); |
262 | } | 263 | } |
263 | // else if (m_storeLocal) | 264 | else if (m_asset.Local) |
264 | // { | 265 | { |
265 | // m_Scene.AssetService.Store(m_asset); | 266 | m_Scene.AssetService.Store(m_asset); |
266 | // } | 267 | } |
267 | } | 268 | } |
268 | 269 | ||
269 | m_log.DebugFormat( | 270 | m_log.DebugFormat( |
@@ -339,7 +340,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
339 | // to avoid a race condition when the appearance module retrieves the item to set the asset id in | 340 | // to avoid a race condition when the appearance module retrieves the item to set the asset id in |
340 | // the AvatarAppearance structure. | 341 | // the AvatarAppearance structure. |
341 | item.AssetID = m_asset.FullID; | 342 | item.AssetID = m_asset.FullID; |
342 | m_Scene.InventoryService.UpdateItem(item); | 343 | if (item.AssetID != UUID.Zero) |
344 | m_Scene.InventoryService.UpdateItem(item); | ||
343 | 345 | ||
344 | if (m_uploadState == UploadState.Complete) | 346 | if (m_uploadState == UploadState.Complete) |
345 | { | 347 | { |
@@ -390,6 +392,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
390 | // m_asset.FullID, item.Name, ourClient.Name); | 392 | // m_asset.FullID, item.Name, ourClient.Name); |
391 | 393 | ||
392 | m_Scene.AssetService.Store(m_asset); | 394 | m_Scene.AssetService.Store(m_asset); |
395 | if (m_asset.FullID != UUID.Zero) | ||
396 | { | ||
397 | item.AssetID = m_asset.FullID; | ||
398 | m_Scene.InventoryService.UpdateItem(item); | ||
399 | } | ||
393 | 400 | ||
394 | m_transactions.RemoveXferUploader(m_transactionID); | 401 | m_transactions.RemoveXferUploader(m_transactionID); |
395 | } | 402 | } |
@@ -424,8 +431,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
424 | item.AssetType = type; | 431 | item.AssetType = type; |
425 | item.InvType = invType; | 432 | item.InvType = invType; |
426 | item.Folder = InventFolder; | 433 | item.Folder = InventFolder; |
427 | item.BasePermissions = 0x7fffffff; | 434 | item.BasePermissions = (uint)(PermissionMask.All | PermissionMask.Export); |
428 | item.CurrentPermissions = 0x7fffffff; | 435 | item.CurrentPermissions = item.BasePermissions; |
429 | item.GroupPermissions=0; | 436 | item.GroupPermissions=0; |
430 | item.EveryOnePermissions=0; | 437 | item.EveryOnePermissions=0; |
431 | item.NextPermissions = nextPerm; | 438 | item.NextPermissions = nextPerm; |
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index a0f1e8c..d510d82 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -363,12 +363,37 @@ namespace OpenSim.Region.CoreModules.Asset | |||
363 | /// Try to get an asset from the file cache. | 363 | /// Try to get an asset from the file cache. |
364 | /// </summary> | 364 | /// </summary> |
365 | /// <param name="id"></param> | 365 | /// <param name="id"></param> |
366 | /// <returns></returns> | 366 | /// <returns>An asset retrieved from the file cache. null if there was a problem retrieving an asset.</returns> |
367 | private AssetBase GetFromFileCache(string id) | 367 | private AssetBase GetFromFileCache(string id) |
368 | { | 368 | { |
369 | string filename = GetFileName(id); | ||
370 | |||
371 | #if WAIT_ON_INPROGRESS_REQUESTS | ||
372 | // Check if we're already downloading this asset. If so, try to wait for it to | ||
373 | // download. | ||
374 | if (m_WaitOnInprogressTimeout > 0) | ||
375 | { | ||
376 | m_RequestsForInprogress++; | ||
377 | |||
378 | ManualResetEvent waitEvent; | ||
379 | 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 | { | ||
390 | m_RequestsForInprogress++; | ||
391 | return null; | ||
392 | } | ||
393 | #endif | ||
394 | |||
369 | AssetBase asset = null; | 395 | AssetBase asset = null; |
370 | 396 | ||
371 | string filename = GetFileName(id); | ||
372 | if (File.Exists(filename)) | 397 | if (File.Exists(filename)) |
373 | { | 398 | { |
374 | FileStream stream = null; | 399 | FileStream stream = null; |
@@ -383,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
383 | } | 408 | } |
384 | catch (System.Runtime.Serialization.SerializationException e) | 409 | catch (System.Runtime.Serialization.SerializationException e) |
385 | { | 410 | { |
386 | m_log.ErrorFormat( | 411 | m_log.WarnFormat( |
387 | "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", | 412 | "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", |
388 | filename, id, e.Message, e.StackTrace); | 413 | filename, id, e.Message, e.StackTrace); |
389 | 414 | ||
@@ -395,9 +420,10 @@ namespace OpenSim.Region.CoreModules.Asset | |||
395 | } | 420 | } |
396 | catch (Exception e) | 421 | catch (Exception e) |
397 | { | 422 | { |
398 | m_log.ErrorFormat( | 423 | m_log.WarnFormat( |
399 | "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", | 424 | "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", |
400 | filename, id, e.Message, e.StackTrace); | 425 | filename, id, e.Message, e.StackTrace); |
426 | |||
401 | } | 427 | } |
402 | finally | 428 | finally |
403 | { | 429 | { |
@@ -406,28 +432,6 @@ namespace OpenSim.Region.CoreModules.Asset | |||
406 | } | 432 | } |
407 | } | 433 | } |
408 | 434 | ||
409 | #if WAIT_ON_INPROGRESS_REQUESTS | ||
410 | // Check if we're already downloading this asset. If so, try to wait for it to | ||
411 | // download. | ||
412 | if (m_WaitOnInprogressTimeout > 0) | ||
413 | { | ||
414 | m_RequestsForInprogress++; | ||
415 | |||
416 | ManualResetEvent waitEvent; | ||
417 | if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) | ||
418 | { | ||
419 | waitEvent.WaitOne(m_WaitOnInprogressTimeout); | ||
420 | return Get(id); | ||
421 | } | ||
422 | } | ||
423 | #else | ||
424 | // Track how often we have the problem that an asset is requested while | ||
425 | // it is still being downloaded by a previous request. | ||
426 | if (m_CurrentlyWriting.Contains(filename)) | ||
427 | { | ||
428 | m_RequestsForInprogress++; | ||
429 | } | ||
430 | #endif | ||
431 | return asset; | 435 | return asset; |
432 | } | 436 | } |
433 | 437 | ||
@@ -552,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
552 | } | 556 | } |
553 | catch (Exception e) | 557 | catch (Exception e) |
554 | { | 558 | { |
555 | m_log.ErrorFormat( | 559 | m_log.WarnFormat( |
556 | "[FLOTSAM ASSET CACHE]: Failed to expire cached file {0}. Exception {1} {2}", | 560 | "[FLOTSAM ASSET CACHE]: Failed to expire cached file {0}. Exception {1} {2}", |
557 | id, e.Message, e.StackTrace); | 561 | id, e.Message, e.StackTrace); |
558 | } | 562 | } |
@@ -603,29 +607,39 @@ namespace OpenSim.Region.CoreModules.Asset | |||
603 | /// <param name="purgeLine"></param> | 607 | /// <param name="purgeLine"></param> |
604 | private void CleanExpiredFiles(string dir, DateTime purgeLine) | 608 | private void CleanExpiredFiles(string dir, DateTime purgeLine) |
605 | { | 609 | { |
606 | foreach (string file in Directory.GetFiles(dir)) | 610 | try |
607 | { | 611 | { |
608 | if (File.GetLastAccessTime(file) < purgeLine) | 612 | foreach (string file in Directory.GetFiles(dir)) |
609 | { | 613 | { |
610 | File.Delete(file); | 614 | if (File.GetLastAccessTime(file) < purgeLine) |
615 | { | ||
616 | File.Delete(file); | ||
617 | } | ||
611 | } | 618 | } |
612 | } | ||
613 | 619 | ||
614 | // Recurse into lower tiers | 620 | // Recurse into lower tiers |
615 | foreach (string subdir in Directory.GetDirectories(dir)) | 621 | foreach (string subdir in Directory.GetDirectories(dir)) |
616 | { | 622 | { |
617 | CleanExpiredFiles(subdir, purgeLine); | 623 | CleanExpiredFiles(subdir, purgeLine); |
618 | } | 624 | } |
619 | 625 | ||
620 | // Check if a tier directory is empty, if so, delete it | 626 | // Check if a tier directory is empty, if so, delete it |
621 | int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length; | 627 | int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length; |
622 | if (dirSize == 0) | 628 | if (dirSize == 0) |
623 | { | 629 | { |
624 | Directory.Delete(dir); | 630 | Directory.Delete(dir); |
631 | } | ||
632 | else if (dirSize >= m_CacheWarnAt) | ||
633 | { | ||
634 | m_log.WarnFormat( | ||
635 | "[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", | ||
636 | dir, dirSize); | ||
637 | } | ||
625 | } | 638 | } |
626 | else if (dirSize >= m_CacheWarnAt) | 639 | catch (Exception e) |
627 | { | 640 | { |
628 | m_log.WarnFormat("[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize); | 641 | m_log.Warn( |
642 | string.Format("[FLOTSAM ASSET CACHE]: Could not complete clean of expired files in {0}, exception ", dir), e); | ||
629 | } | 643 | } |
630 | } | 644 | } |
631 | 645 | ||
@@ -684,7 +698,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
684 | } | 698 | } |
685 | catch (IOException e) | 699 | catch (IOException e) |
686 | { | 700 | { |
687 | m_log.ErrorFormat( | 701 | m_log.WarnFormat( |
688 | "[FLOTSAM ASSET CACHE]: Failed to write asset {0} to temporary location {1} (final {2}) on cache in {3}. Exception {4} {5}.", | 702 | "[FLOTSAM ASSET CACHE]: Failed to write asset {0} to temporary location {1} (final {2}) on cache in {3}. Exception {4} {5}.", |
689 | asset.ID, tempname, filename, directory, e.Message, e.StackTrace); | 703 | asset.ID, tempname, filename, directory, e.Message, e.StackTrace); |
690 | 704 | ||
@@ -763,17 +777,31 @@ namespace OpenSim.Region.CoreModules.Asset | |||
763 | /// <summary> | 777 | /// <summary> |
764 | /// This notes the last time the Region had a deep asset scan performed on it. | 778 | /// This notes the last time the Region had a deep asset scan performed on it. |
765 | /// </summary> | 779 | /// </summary> |
766 | /// <param name="RegionID"></param> | 780 | /// <param name="regionID"></param> |
767 | private void StampRegionStatusFile(UUID RegionID) | 781 | private void StampRegionStatusFile(UUID regionID) |
768 | { | 782 | { |
769 | string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + RegionID.ToString() + ".fac"); | 783 | string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + regionID.ToString() + ".fac"); |
770 | if (File.Exists(RegionCacheStatusFile)) | 784 | |
785 | try | ||
771 | { | 786 | { |
772 | File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now); | 787 | if (File.Exists(RegionCacheStatusFile)) |
788 | { | ||
789 | File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now); | ||
790 | } | ||
791 | else | ||
792 | { | ||
793 | File.WriteAllText( | ||
794 | RegionCacheStatusFile, | ||
795 | "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache."); | ||
796 | } | ||
773 | } | 797 | } |
774 | else | 798 | catch (Exception e) |
775 | { | 799 | { |
776 | File.WriteAllText(RegionCacheStatusFile, "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache."); | 800 | m_log.Warn( |
801 | string.Format( | ||
802 | "[FLOTSAM ASSET CACHE]: Could not stamp region status file for region {0}. Exception ", | ||
803 | regionID), | ||
804 | e); | ||
777 | } | 805 | } |
778 | } | 806 | } |
779 | 807 | ||
@@ -790,32 +818,43 @@ namespace OpenSim.Region.CoreModules.Asset | |||
790 | { | 818 | { |
791 | UuidGatherer gatherer = new UuidGatherer(m_AssetService); | 819 | UuidGatherer gatherer = new UuidGatherer(m_AssetService); |
792 | 820 | ||
821 | HashSet<UUID> uniqueUuids = new HashSet<UUID>(); | ||
793 | Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); | 822 | Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); |
823 | |||
794 | foreach (Scene s in m_Scenes) | 824 | foreach (Scene s in m_Scenes) |
795 | { | 825 | { |
796 | StampRegionStatusFile(s.RegionInfo.RegionID); | 826 | StampRegionStatusFile(s.RegionInfo.RegionID); |
797 | 827 | ||
798 | s.ForEachSOG(delegate(SceneObjectGroup e) | 828 | s.ForEachSOG(delegate(SceneObjectGroup e) |
799 | { | 829 | { |
800 | gatherer.GatherAssetUuids(e, assets); | 830 | gatherer.GatherAssetUuids(e, assets); |
801 | }); | ||
802 | } | ||
803 | 831 | ||
804 | foreach (UUID assetID in assets.Keys) | 832 | foreach (UUID assetID in assets.Keys) |
805 | { | 833 | { |
806 | string filename = GetFileName(assetID.ToString()); | 834 | uniqueUuids.Add(assetID); |
807 | 835 | ||
808 | if (File.Exists(filename)) | 836 | string filename = GetFileName(assetID.ToString()); |
809 | { | 837 | |
810 | File.SetLastAccessTime(filename, DateTime.Now); | 838 | if (File.Exists(filename)) |
811 | } | 839 | { |
812 | else if (storeUncached) | 840 | File.SetLastAccessTime(filename, DateTime.Now); |
813 | { | 841 | } |
814 | m_AssetService.Get(assetID.ToString()); | 842 | else if (storeUncached) |
815 | } | 843 | { |
844 | AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); | ||
845 | if (cachedAsset == null && assets[assetID] != AssetType.Unknown) | ||
846 | m_log.DebugFormat( | ||
847 | "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", | ||
848 | assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); | ||
849 | } | ||
850 | } | ||
851 | |||
852 | assets.Clear(); | ||
853 | }); | ||
816 | } | 854 | } |
817 | 855 | ||
818 | return assets.Keys.Count; | 856 | |
857 | return uniqueUuids.Count; | ||
819 | } | 858 | } |
820 | 859 | ||
821 | /// <summary> | 860 | /// <summary> |
@@ -831,7 +870,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
831 | } | 870 | } |
832 | catch (Exception e) | 871 | catch (Exception e) |
833 | { | 872 | { |
834 | m_log.ErrorFormat( | 873 | m_log.WarnFormat( |
835 | "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache directory {0} from {1}. Exception {2} {3}", | 874 | "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache directory {0} from {1}. Exception {2} {3}", |
836 | dir, m_CacheDirectory, e.Message, e.StackTrace); | 875 | dir, m_CacheDirectory, e.Message, e.StackTrace); |
837 | } | 876 | } |
@@ -845,7 +884,7 @@ namespace OpenSim.Region.CoreModules.Asset | |||
845 | } | 884 | } |
846 | catch (Exception e) | 885 | catch (Exception e) |
847 | { | 886 | { |
848 | m_log.ErrorFormat( | 887 | m_log.WarnFormat( |
849 | "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache file {0} from {1}. Exception {1} {2}", | 888 | "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache file {0} from {1}. Exception {1} {2}", |
850 | file, m_CacheDirectory, e.Message, e.StackTrace); | 889 | file, m_CacheDirectory, e.Message, e.StackTrace); |
851 | } | 890 | } |
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index 1c2bfd0..fd02b08 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs | |||
@@ -47,14 +47,16 @@ namespace OpenSim.Region.CoreModules.Asset.Tests | |||
47 | /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. | 47 | /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. |
48 | /// </summary> | 48 | /// </summary> |
49 | [TestFixture] | 49 | [TestFixture] |
50 | public class FlotsamAssetCacheTests | 50 | public class FlotsamAssetCacheTests : OpenSimTestCase |
51 | { | 51 | { |
52 | protected TestScene m_scene; | 52 | protected TestScene m_scene; |
53 | protected FlotsamAssetCache m_cache; | 53 | protected FlotsamAssetCache m_cache; |
54 | 54 | ||
55 | [SetUp] | 55 | [SetUp] |
56 | public void SetUp() | 56 | public override void SetUp() |
57 | { | 57 | { |
58 | base.SetUp(); | ||
59 | |||
58 | IConfigSource config = new IniConfigSource(); | 60 | IConfigSource config = new IniConfigSource(); |
59 | 61 | ||
60 | config.AddConfig("Modules"); | 62 | config.AddConfig("Modules"); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index acd156e..cb724aa 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
49 | { | 49 | { |
50 | #region INonSharedRegionModule | 50 | #region INonSharedRegionModule |
51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
52 | |||
53 | public int DebugLevel { get; set; } | ||
52 | 54 | ||
53 | private Scene m_scene; | 55 | private Scene m_scene; |
54 | private IInventoryAccessModule m_invAccessModule; | 56 | private IInventoryAccessModule m_invAccessModule; |
@@ -76,10 +78,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
76 | m_scene.RegisterModuleInterface<IAttachmentsModule>(this); | 78 | m_scene.RegisterModuleInterface<IAttachmentsModule>(this); |
77 | 79 | ||
78 | if (Enabled) | 80 | if (Enabled) |
81 | { | ||
79 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; | 82 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; |
83 | m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); | ||
84 | m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); | ||
85 | |||
86 | MainConsole.Instance.Commands.AddCommand( | ||
87 | "Debug", | ||
88 | false, | ||
89 | "debug attachments", | ||
90 | "debug attachments [0|1]", | ||
91 | "Turn on attachments debugging\n" | ||
92 | + " <= 0 - turns off debugging\n" | ||
93 | + " >= 1 - turns on attachment message logging\n", | ||
94 | HandleDebugAttachments); | ||
95 | } | ||
80 | 96 | ||
81 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI | 97 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI |
82 | } | 98 | } |
99 | |||
100 | private void HandleDebugAttachments(string module, string[] args) | ||
101 | { | ||
102 | int debugLevel; | ||
103 | |||
104 | if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) | ||
105 | { | ||
106 | MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | DebugLevel = debugLevel; | ||
111 | MainConsole.Instance.OutputFormat( | ||
112 | "Set event queue debug level to {0} in {1}", DebugLevel, m_scene.Name); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /// <summary> | ||
117 | /// Listen for client triggered running state changes so that we can persist the script's object if necessary. | ||
118 | /// </summary> | ||
119 | /// <param name='localID'></param> | ||
120 | /// <param name='itemID'></param> | ||
121 | private void HandleScriptStateChange(uint localID, bool started) | ||
122 | { | ||
123 | SceneObjectGroup sog = m_scene.GetGroupByPrim(localID); | ||
124 | if (sog != null && sog.IsAttachment) | ||
125 | { | ||
126 | if (!started) | ||
127 | { | ||
128 | // FIXME: This is a convoluted way for working out whether the script state has changed to stop | ||
129 | // because it has been manually stopped or because the stop was called in UpdateDetachedObject() below | ||
130 | // This needs to be handled in a less tangled way. | ||
131 | ScenePresence sp = m_scene.GetScenePresence(sog.AttachedAvatar); | ||
132 | if (sp.ControllingClient.IsActive) | ||
133 | sog.HasGroupChanged = true; | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | sog.HasGroupChanged = true; | ||
138 | } | ||
139 | } | ||
140 | } | ||
83 | 141 | ||
84 | public void RemoveRegion(Scene scene) | 142 | public void RemoveRegion(Scene scene) |
85 | { | 143 | { |
@@ -153,10 +211,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
153 | } | 211 | } |
154 | } | 212 | } |
155 | 213 | ||
156 | /// <summary> | ||
157 | /// RezAttachments. This should only be called upon login on the first region. | ||
158 | /// Attachment rezzings on crossings and TPs are done in a different way. | ||
159 | /// </summary> | ||
160 | public void RezAttachments(IScenePresence sp) | 214 | public void RezAttachments(IScenePresence sp) |
161 | { | 215 | { |
162 | if (!Enabled) | 216 | if (!Enabled) |
@@ -165,10 +219,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
165 | if (null == sp.Appearance) | 219 | if (null == sp.Appearance) |
166 | { | 220 | { |
167 | m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID); | 221 | m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID); |
222 | |||
168 | return; | 223 | return; |
169 | } | 224 | } |
170 | 225 | ||
171 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name); | 226 | if (sp.GetAttachments().Count > 0) |
227 | { | ||
228 | if (DebugLevel > 0) | ||
229 | m_log.DebugFormat( | ||
230 | "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments", | ||
231 | m_scene.Name, sp.Name); | ||
232 | |||
233 | return; | ||
234 | } | ||
235 | |||
236 | if (DebugLevel > 0) | ||
237 | m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); | ||
172 | 238 | ||
173 | XmlDocument doc = new XmlDocument(); | 239 | XmlDocument doc = new XmlDocument(); |
174 | string stateData = String.Empty; | 240 | string stateData = String.Empty; |
@@ -235,10 +301,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
235 | 301 | ||
236 | // If we're an NPC then skip all the item checks and manipulations since we don't have an | 302 | // If we're an NPC then skip all the item checks and manipulations since we don't have an |
237 | // inventory right now. | 303 | // inventory right now. |
238 | if (sp.PresenceType == PresenceType.Npc) | 304 | RezSingleAttachmentFromInventoryInternal( |
239 | RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null); | 305 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, null); |
240 | else | ||
241 | RezSingleAttachmentFromInventory(sp, attach.ItemID, p, d); | ||
242 | } | 306 | } |
243 | catch (Exception e) | 307 | catch (Exception e) |
244 | { | 308 | { |
@@ -254,14 +318,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
254 | if (!Enabled) | 318 | if (!Enabled) |
255 | return; | 319 | return; |
256 | 320 | ||
257 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); | 321 | if (DebugLevel > 0) |
322 | m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); | ||
323 | |||
324 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
325 | |||
326 | if (attachments.Count <= 0) | ||
327 | return; | ||
328 | |||
329 | Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); | ||
330 | |||
331 | foreach (SceneObjectGroup so in attachments) | ||
332 | { | ||
333 | // Scripts MUST be snapshotted before the object is | ||
334 | // removed from the scene because doing otherwise will | ||
335 | // clobber the run flag | ||
336 | // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from | ||
337 | // scripts performing attachment operations at the same time. Getting object states stops the scripts. | ||
338 | scriptStates[so] = PrepareScriptInstanceForSave(so, false); | ||
339 | } | ||
258 | 340 | ||
259 | lock (sp.AttachmentsSyncLock) | 341 | lock (sp.AttachmentsSyncLock) |
260 | { | 342 | { |
261 | foreach (SceneObjectGroup so in sp.GetAttachments()) | 343 | foreach (SceneObjectGroup so in attachments) |
262 | { | 344 | UpdateDetachedObject(sp, so, scriptStates[so]); |
263 | UpdateDetachedObject(sp, so); | ||
264 | } | ||
265 | 345 | ||
266 | sp.ClearAttachments(); | 346 | sp.ClearAttachments(); |
267 | } | 347 | } |
@@ -272,9 +352,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
272 | if (!Enabled) | 352 | if (!Enabled) |
273 | return; | 353 | return; |
274 | 354 | ||
275 | // m_log.DebugFormat( | 355 | if (DebugLevel > 0) |
276 | // "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", | 356 | m_log.DebugFormat( |
277 | // m_scene.RegionInfo.RegionName, sp.Name, silent); | 357 | "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", |
358 | m_scene.RegionInfo.RegionName, sp.Name, silent); | ||
278 | 359 | ||
279 | foreach (SceneObjectGroup sop in sp.GetAttachments()) | 360 | foreach (SceneObjectGroup sop in sp.GetAttachments()) |
280 | { | 361 | { |
@@ -284,131 +365,141 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
284 | sp.ClearAttachments(); | 365 | sp.ClearAttachments(); |
285 | } | 366 | } |
286 | 367 | ||
287 | public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) | 368 | public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append) |
288 | { | 369 | { |
289 | if (!Enabled) | 370 | if (!Enabled) |
290 | return false; | 371 | return false; |
291 | 372 | ||
292 | if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp)) | 373 | return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append); |
293 | { | ||
294 | m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); | ||
295 | return true; | ||
296 | } | ||
297 | |||
298 | return false; | ||
299 | } | 374 | } |
300 | 375 | ||
301 | private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) | 376 | /// <summary> |
377 | /// Internal method which actually does all the work for attaching an object. | ||
378 | /// </summary> | ||
379 | /// <returns>The object attached.</returns> | ||
380 | /// <param name='sp'></param> | ||
381 | /// <param name='group'>The object to attach.</param> | ||
382 | /// <param name='attachmentPt'></param> | ||
383 | /// <param name='silent'></param> | ||
384 | /// <param name='addToInventory'>If true then add object to user inventory.</param> | ||
385 | /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> | ||
386 | private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append) | ||
302 | { | 387 | { |
303 | lock (sp.AttachmentsSyncLock) | ||
304 | { | ||
305 | // m_log.DebugFormat( | 388 | // m_log.DebugFormat( |
306 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", | 389 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", |
307 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); | 390 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); |
308 | 391 | ||
309 | if (group.GetSittingAvatarsCount() != 0) | 392 | if (sp.GetAttachments().Contains(group)) |
310 | { | 393 | { |
311 | // m_log.WarnFormat( | 394 | // m_log.WarnFormat( |
312 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", | 395 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", |
313 | // group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); | 396 | // group.Name, group.LocalId, sp.Name, AttachmentPt); |
314 | 397 | ||
315 | return false; | 398 | return false; |
316 | } | 399 | } |
317 | 400 | ||
318 | if (sp.GetAttachments(attachmentPt).Contains(group)) | 401 | if (group.GetSittingAvatarsCount() != 0) |
319 | { | 402 | { |
320 | // m_log.WarnFormat( | 403 | if (DebugLevel > 0) |
321 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | 404 | m_log.WarnFormat( |
322 | // group.Name, group.LocalId, sp.Name, AttachmentPt); | 405 | "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", |
323 | 406 | group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); | |
324 | return false; | 407 | |
325 | } | 408 | return false; |
326 | 409 | } | |
327 | Vector3 attachPos = group.AbsolutePosition; | 410 | |
328 | 411 | Vector3 attachPos = group.AbsolutePosition; | |
329 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | 412 | |
330 | // be removed when that functionality is implemented in opensim | 413 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should |
331 | attachmentPt &= 0x7f; | 414 | // be removed when that functionality is implemented in opensim |
332 | 415 | attachmentPt &= 0x7f; | |
333 | // If the attachment point isn't the same as the one previously used | 416 | |
334 | // set it's offset position = 0 so that it appears on the attachment point | 417 | // If the attachment point isn't the same as the one previously used |
335 | // and not in a weird location somewhere unknown. | 418 | // set it's offset position = 0 so that it appears on the attachment point |
336 | if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) | 419 | // and not in a weird location somewhere unknown. |
337 | { | 420 | if (attachmentPt != (uint)AttachmentPoint.Default && attachmentPt != group.AttachmentPoint) |
338 | attachPos = Vector3.Zero; | 421 | { |
339 | } | 422 | attachPos = Vector3.Zero; |
340 | 423 | } | |
341 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | 424 | |
342 | if (attachmentPt == 0) | 425 | // AttachmentPt 0 (default) means the client chose to 'wear' the attachment. |
343 | { | 426 | if (attachmentPt == (uint)AttachmentPoint.Default) |
344 | // Check object for stored attachment point | 427 | { |
345 | attachmentPt = group.AttachmentPoint; | 428 | // Check object for stored attachment point |
346 | } | 429 | attachmentPt = group.AttachmentPoint; |
347 | 430 | } | |
348 | // if we still didn't find a suitable attachment point....... | 431 | |
349 | if (attachmentPt == 0) | 432 | // if we still didn't find a suitable attachment point....... |
350 | { | 433 | if (attachmentPt == 0) |
351 | // Stick it on left hand with Zero Offset from the attachment point. | 434 | { |
352 | attachmentPt = (uint)AttachmentPoint.LeftHand; | 435 | // Stick it on left hand with Zero Offset from the attachment point. |
353 | attachPos = Vector3.Zero; | 436 | attachmentPt = (uint)AttachmentPoint.LeftHand; |
354 | } | 437 | attachPos = Vector3.Zero; |
355 | 438 | } | |
356 | if (useAttachData) | 439 | |
440 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
441 | |||
442 | if (attachments.Contains(group)) | ||
443 | { | ||
444 | if (DebugLevel > 0) | ||
445 | m_log.WarnFormat( | ||
446 | "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | ||
447 | group.Name, group.LocalId, sp.Name, attachmentPt); | ||
448 | |||
449 | return false; | ||
450 | } | ||
451 | |||
452 | // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones | ||
453 | while (attachments.Count >= 5) | ||
454 | { | ||
455 | if (attachments[0].FromItemID != UUID.Zero) | ||
456 | DetachSingleAttachmentToInv(sp, attachments[0]); | ||
457 | attachments.RemoveAt(0); | ||
458 | } | ||
459 | |||
460 | // If we're not appending, remove the rest as well | ||
461 | if (attachments.Count != 0 && !append) | ||
462 | { | ||
463 | foreach (SceneObjectGroup g in attachments) | ||
357 | { | 464 | { |
358 | group.RootPart.RotationOffset = group.RootPart.AttachRotation; | 465 | if (g.FromItemID != UUID.Zero) |
359 | attachPos = group.RootPart.AttachOffset; | 466 | DetachSingleAttachmentToInv(sp, g); |
360 | if (attachmentPt == 0) | ||
361 | { | ||
362 | attachmentPt = group.RootPart.AttachPoint; | ||
363 | if (attachmentPt == 0) | ||
364 | { | ||
365 | attachmentPt = (uint)AttachmentPoint.LeftHand; | ||
366 | attachPos = Vector3.Zero; | ||
367 | } | ||
368 | } | ||
369 | else if (group.RootPart.AttachPoint != attachmentPt) | ||
370 | { | ||
371 | attachPos = Vector3.Zero; | ||
372 | } | ||
373 | } | 467 | } |
468 | } | ||
469 | |||
470 | lock (sp.AttachmentsSyncLock) | ||
471 | { | ||
374 | group.AttachmentPoint = attachmentPt; | 472 | group.AttachmentPoint = attachmentPt; |
375 | group.AbsolutePosition = attachPos; | 473 | group.AbsolutePosition = attachPos; |
376 | 474 | ||
377 | if (sp.PresenceType != PresenceType.Npc) | 475 | if (addToInventory && sp.PresenceType != PresenceType.Npc) |
378 | UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp); | 476 | UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); |
379 | 477 | ||
380 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); | 478 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); |
479 | |||
480 | if (resumeScripts) | ||
481 | { | ||
482 | // Fire after attach, so we don't get messy perms dialogs | ||
483 | // 4 == AttachedRez | ||
484 | group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | ||
485 | group.ResumeScripts(); | ||
486 | } | ||
487 | |||
488 | // Do this last so that event listeners have access to all the effects of the attachment | ||
489 | m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); | ||
381 | } | 490 | } |
382 | 491 | ||
383 | return true; | 492 | return true; |
384 | } | 493 | } |
385 | 494 | ||
386 | private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp) | 495 | private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool append) |
387 | { | 496 | { |
388 | // Remove any previous attachments | ||
389 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
390 | |||
391 | // At the moment we can only deal with a single attachment | ||
392 | if (attachments.Count != 0) | ||
393 | { | ||
394 | if (attachments[0].FromItemID != UUID.Zero) | ||
395 | DetachSingleAttachmentToInvInternal(sp, attachments[0]); | ||
396 | // Error logging commented because UUID.Zero now means temp attachment | ||
397 | // else | ||
398 | // m_log.WarnFormat( | ||
399 | // "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", | ||
400 | // attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); | ||
401 | } | ||
402 | |||
403 | // Add the new attachment to inventory if we don't already have it. | 497 | // Add the new attachment to inventory if we don't already have it. |
404 | if (!temp) | 498 | UUID newAttachmentItemID = group.FromItemID; |
405 | { | 499 | if (newAttachmentItemID == UUID.Zero) |
406 | UUID newAttachmentItemID = group.FromItemID; | 500 | newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; |
407 | if (newAttachmentItemID == UUID.Zero) | ||
408 | newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; | ||
409 | 501 | ||
410 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); | 502 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); |
411 | } | ||
412 | } | 503 | } |
413 | 504 | ||
414 | public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) | 505 | public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) |
@@ -421,41 +512,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
421 | if (!Enabled) | 512 | if (!Enabled) |
422 | return null; | 513 | return null; |
423 | 514 | ||
424 | // m_log.DebugFormat( | 515 | if (DebugLevel > 0) |
425 | // "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", | 516 | m_log.DebugFormat( |
426 | // (AttachmentPoint)AttachmentPt, itemID, sp.Name); | 517 | "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}", |
427 | 518 | (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); | |
428 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | ||
429 | // be removed when that functionality is implemented in opensim | ||
430 | AttachmentPt &= 0x7f; | ||
431 | 519 | ||
432 | // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). | 520 | // We check the attachments in the avatar appearance here rather than the objects attached to the |
433 | // This often happens during login - not sure the exact reason. | 521 | // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are |
434 | // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the | 522 | // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done |
435 | // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login | 523 | // because pre-outfit folder viewers (most version 1 viewers) require it. |
436 | // before anything has actually been attached. | ||
437 | bool alreadyOn = false; | 524 | bool alreadyOn = false; |
438 | List<SceneObjectGroup> existingAttachments = sp.GetAttachments(); | 525 | List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments(); |
439 | foreach (SceneObjectGroup so in existingAttachments) | 526 | foreach (AvatarAttachment existingAttachment in existingAttachments) |
440 | { | 527 | { |
441 | if (so.FromItemID == itemID) | 528 | if (existingAttachment.ItemID == itemID) |
442 | { | 529 | { |
443 | alreadyOn = true; | 530 | alreadyOn = true; |
444 | break; | 531 | break; |
445 | } | 532 | } |
446 | } | 533 | } |
447 | 534 | ||
448 | // if (sp.Appearance.GetAttachmentForItem(itemID) != null) | ||
449 | if (alreadyOn) | 535 | if (alreadyOn) |
450 | { | 536 | { |
451 | // m_log.WarnFormat( | 537 | if (DebugLevel > 0) |
452 | // "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn", | 538 | m_log.DebugFormat( |
453 | // sp.Name, itemID, AttachmentPt); | 539 | "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn", |
540 | sp.Name, itemID, AttachmentPt); | ||
454 | 541 | ||
455 | return null; | 542 | return null; |
456 | } | 543 | } |
457 | 544 | ||
458 | return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc); | 545 | bool append = (AttachmentPt & 0x80) != 0; |
546 | AttachmentPt &= 0x7f; | ||
547 | |||
548 | return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc); | ||
459 | } | 549 | } |
460 | 550 | ||
461 | public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) | 551 | public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) |
@@ -463,13 +553,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
463 | if (!Enabled) | 553 | if (!Enabled) |
464 | return; | 554 | return; |
465 | 555 | ||
466 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name); | 556 | if (DebugLevel > 0) |
467 | lock (sp.AttachmentsSyncLock) | 557 | m_log.DebugFormat( |
558 | "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}", | ||
559 | rezlist.Count, sp.Name, m_scene.Name); | ||
560 | |||
561 | foreach (KeyValuePair<UUID, uint> rez in rezlist) | ||
468 | { | 562 | { |
469 | foreach (KeyValuePair<UUID, uint> rez in rezlist) | 563 | RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value); |
470 | { | ||
471 | RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value); | ||
472 | } | ||
473 | } | 564 | } |
474 | } | 565 | } |
475 | 566 | ||
@@ -483,9 +574,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
483 | if (!Enabled) | 574 | if (!Enabled) |
484 | return; | 575 | return; |
485 | 576 | ||
486 | // m_log.DebugFormat( | 577 | if (DebugLevel > 0) |
487 | // "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", | 578 | m_log.DebugFormat( |
488 | // sp.UUID, soLocalId); | 579 | "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", |
580 | sp.UUID, soLocalId); | ||
489 | 581 | ||
490 | SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); | 582 | SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); |
491 | 583 | ||
@@ -501,9 +593,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
501 | if (inventoryID == UUID.Zero) | 593 | if (inventoryID == UUID.Zero) |
502 | return; | 594 | return; |
503 | 595 | ||
504 | // m_log.DebugFormat( | 596 | if (DebugLevel > 0) |
505 | // "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", | 597 | m_log.DebugFormat( |
506 | // so.Name, so.LocalId, inventoryID); | 598 | "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", |
599 | so.Name, so.LocalId, inventoryID); | ||
507 | 600 | ||
508 | lock (sp.AttachmentsSyncLock) | 601 | lock (sp.AttachmentsSyncLock) |
509 | { | 602 | { |
@@ -549,25 +642,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
549 | 642 | ||
550 | public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) | 643 | public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) |
551 | { | 644 | { |
645 | if (so.AttachedAvatar != sp.UUID) | ||
646 | { | ||
647 | m_log.WarnFormat( | ||
648 | "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}", | ||
649 | so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName); | ||
650 | |||
651 | return; | ||
652 | } | ||
653 | |||
654 | if (DebugLevel > 0) | ||
655 | m_log.DebugFormat( | ||
656 | "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", | ||
657 | so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name); | ||
658 | |||
659 | // Scripts MUST be snapshotted before the object is | ||
660 | // removed from the scene because doing otherwise will | ||
661 | // clobber the run flag | ||
662 | // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from | ||
663 | // scripts performing attachment operations at the same time. Getting object states stops the scripts. | ||
664 | string scriptedState = PrepareScriptInstanceForSave(so, true); | ||
665 | |||
552 | lock (sp.AttachmentsSyncLock) | 666 | lock (sp.AttachmentsSyncLock) |
553 | { | 667 | { |
554 | // Save avatar attachment information | 668 | // Save avatar attachment information |
555 | // m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID); | 669 | // m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID); |
556 | 670 | ||
557 | if (so.AttachedAvatar != sp.UUID) | ||
558 | { | ||
559 | m_log.WarnFormat( | ||
560 | "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}", | ||
561 | so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName); | ||
562 | |||
563 | return; | ||
564 | } | ||
565 | |||
566 | bool changed = sp.Appearance.DetachAttachment(so.FromItemID); | 671 | bool changed = sp.Appearance.DetachAttachment(so.FromItemID); |
567 | if (changed && m_scene.AvatarFactory != null) | 672 | if (changed && m_scene.AvatarFactory != null) |
568 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | 673 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); |
569 | 674 | ||
570 | DetachSingleAttachmentToInvInternal(sp, so); | 675 | sp.RemoveAttachment(so); |
676 | UpdateDetachedObject(sp, so, scriptedState); | ||
571 | } | 677 | } |
572 | } | 678 | } |
573 | 679 | ||
@@ -674,12 +780,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
674 | 780 | ||
675 | grp.HasGroupChanged = false; // Prevent it being saved over and over | 781 | grp.HasGroupChanged = false; // Prevent it being saved over and over |
676 | } | 782 | } |
677 | // else | 783 | else if (DebugLevel > 0) |
678 | // { | 784 | { |
679 | // m_log.DebugFormat( | 785 | m_log.DebugFormat( |
680 | // "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", | 786 | "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", |
681 | // grp.UUID, grp.AttachmentPoint); | 787 | grp.UUID, grp.AttachmentPoint); |
682 | // } | 788 | } |
683 | } | 789 | } |
684 | 790 | ||
685 | /// <summary> | 791 | /// <summary> |
@@ -697,9 +803,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
697 | private void AttachToAgent( | 803 | private void AttachToAgent( |
698 | IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) | 804 | IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) |
699 | { | 805 | { |
700 | // m_log.DebugFormat( | 806 | if (DebugLevel > 0) |
701 | // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", | 807 | m_log.DebugFormat( |
702 | // so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); | 808 | "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", |
809 | so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); | ||
703 | 810 | ||
704 | so.DetachFromBackup(); | 811 | so.DetachFromBackup(); |
705 | 812 | ||
@@ -722,19 +829,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
722 | 829 | ||
723 | if (!silent) | 830 | if (!silent) |
724 | { | 831 | { |
725 | // Killing it here will cause the client to deselect it | 832 | if (so.HasPrivateAttachmentPoint) |
726 | // It then reappears on the avatar, deselected | ||
727 | // through the full update below | ||
728 | // | ||
729 | if (so.IsSelected) | ||
730 | { | 833 | { |
731 | m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId }); | 834 | if (DebugLevel > 0) |
732 | } | 835 | m_log.DebugFormat( |
733 | else if (so.HasPrivateAttachmentPoint) | 836 | "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}", |
734 | { | 837 | so.Name, sp.Name, so.AttachmentPoint); |
735 | // m_log.DebugFormat( | ||
736 | // "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}", | ||
737 | // so.Name, sp.Name, so.AttachmentPoint); | ||
738 | 838 | ||
739 | // As this scene object can now only be seen by the attaching avatar, tell everybody else in the | 839 | // As this scene object can now only be seen by the attaching avatar, tell everybody else in the |
740 | // scene that it's no longer in their awareness. | 840 | // scene that it's no longer in their awareness. |
@@ -745,7 +845,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
745 | }); | 845 | }); |
746 | } | 846 | } |
747 | 847 | ||
748 | so.IsSelected = false; // fudge.... | 848 | // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update |
849 | // will succeed, as that will not update if an attachment is selected. | ||
850 | so.IsSelected = false; // fudge.... | ||
851 | |||
749 | so.ScheduleGroupForFullUpdate(); | 852 | so.ScheduleGroupForFullUpdate(); |
750 | } | 853 | } |
751 | 854 | ||
@@ -765,9 +868,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
765 | if (m_invAccessModule == null) | 868 | if (m_invAccessModule == null) |
766 | return null; | 869 | return null; |
767 | 870 | ||
768 | // m_log.DebugFormat( | 871 | if (DebugLevel > 0) |
769 | // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", | 872 | m_log.DebugFormat( |
770 | // grp.Name, grp.LocalId, remoteClient.Name); | 873 | "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", |
874 | grp.Name, grp.LocalId, sp.Name); | ||
771 | 875 | ||
772 | InventoryItemBase newItem | 876 | InventoryItemBase newItem |
773 | = m_invAccessModule.CopyToInventory( | 877 | = m_invAccessModule.CopyToInventory( |
@@ -782,8 +886,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
782 | return newItem; | 886 | return newItem; |
783 | } | 887 | } |
784 | 888 | ||
785 | private string GetObjectScriptStates(SceneObjectGroup grp) | 889 | /// <summary> |
890 | /// Prepares the script instance for save. | ||
891 | /// </summary> | ||
892 | /// <remarks> | ||
893 | /// This involves triggering the detach event and getting the script state (which also stops the script) | ||
894 | /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a | ||
895 | /// running script is performing attachment operations. | ||
896 | /// </remarks> | ||
897 | /// <returns> | ||
898 | /// The script state ready for persistence. | ||
899 | /// </returns> | ||
900 | /// <param name='grp'> | ||
901 | /// </param> | ||
902 | /// <param name='fireDetachEvent'> | ||
903 | /// If true, then fire the script event before we save its state. | ||
904 | /// </param> | ||
905 | private string PrepareScriptInstanceForSave(SceneObjectGroup grp, bool fireDetachEvent) | ||
786 | { | 906 | { |
907 | if (fireDetachEvent) | ||
908 | m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero); | ||
909 | |||
787 | using (StringWriter sw = new StringWriter()) | 910 | using (StringWriter sw = new StringWriter()) |
788 | { | 911 | { |
789 | using (XmlTextWriter writer = new XmlTextWriter(sw)) | 912 | using (XmlTextWriter writer = new XmlTextWriter(sw)) |
@@ -795,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
795 | } | 918 | } |
796 | } | 919 | } |
797 | 920 | ||
798 | private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so) | 921 | private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so, string scriptedState) |
799 | { | 922 | { |
800 | // Don't save attachments for HG visitors, it | 923 | // Don't save attachments for HG visitors, it |
801 | // messes up their inventory. When a HG visitor logs | 924 | // messes up their inventory. When a HG visitor logs |
@@ -808,11 +931,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
808 | && (m_scene.UserManagementModule == null | 931 | && (m_scene.UserManagementModule == null |
809 | || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); | 932 | || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); |
810 | 933 | ||
811 | // Scripts MUST be snapshotted before the object is | ||
812 | // removed from the scene because doing otherwise will | ||
813 | // clobber the run flag | ||
814 | string scriptedState = GetObjectScriptStates(so); | ||
815 | |||
816 | // Remove the object from the scene so no more updates | 934 | // Remove the object from the scene so no more updates |
817 | // are sent. Doing this before the below changes will ensure | 935 | // are sent. Doing this before the below changes will ensure |
818 | // updates can't cause "HUD artefacts" | 936 | // updates can't cause "HUD artefacts" |
@@ -836,97 +954,75 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
836 | so.RemoveScriptInstances(true); | 954 | so.RemoveScriptInstances(true); |
837 | } | 955 | } |
838 | 956 | ||
839 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) | ||
840 | { | ||
841 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | ||
842 | |||
843 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); | ||
844 | sp.RemoveAttachment(so); | ||
845 | |||
846 | UpdateDetachedObject(sp, so); | ||
847 | } | ||
848 | |||
849 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( | 957 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( |
850 | IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc) | 958 | IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc) |
851 | { | 959 | { |
852 | if (m_invAccessModule == null) | 960 | if (m_invAccessModule == null) |
853 | return null; | 961 | return null; |
854 | 962 | ||
855 | lock (sp.AttachmentsSyncLock) | 963 | SceneObjectGroup objatt; |
964 | |||
965 | if (itemID != UUID.Zero) | ||
966 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | ||
967 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
968 | false, false, sp.UUID, true); | ||
969 | else | ||
970 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | ||
971 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
972 | false, false, sp.UUID, true); | ||
973 | |||
974 | if (objatt == null) | ||
856 | { | 975 | { |
857 | SceneObjectGroup objatt; | 976 | m_log.WarnFormat( |
977 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", | ||
978 | itemID, sp.Name, attachmentPt); | ||
858 | 979 | ||
859 | if (itemID != UUID.Zero) | 980 | return null; |
860 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | 981 | } |
861 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
862 | false, false, sp.UUID, true); | ||
863 | else | ||
864 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | ||
865 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
866 | false, false, sp.UUID, true); | ||
867 | 982 | ||
868 | if (objatt != null) | 983 | if (DebugLevel > 0) |
984 | m_log.DebugFormat( | ||
985 | "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | ||
986 | objatt.Name, sp.Name, attachmentPt, m_scene.Name); | ||
987 | |||
988 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | ||
989 | objatt.HasGroupChanged = false; | ||
990 | bool tainted = false; | ||
991 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) | ||
992 | tainted = true; | ||
993 | |||
994 | // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal | ||
995 | // course of events. If not, then it's probably not worth trying to recover the situation | ||
996 | // since this is more likely to trigger further exceptions and confuse later debugging. If | ||
997 | // exceptions can be thrown in expected error conditions (not NREs) then make this consistent | ||
998 | // since other normal error conditions will simply return false instead. | ||
999 | // This will throw if the attachment fails | ||
1000 | try | ||
1001 | { | ||
1002 | if (doc != null) | ||
869 | { | 1003 | { |
870 | // m_log.DebugFormat( | 1004 | objatt.LoadScriptState(doc); |
871 | // "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | 1005 | objatt.ResetOwnerChangeFlag(); |
872 | // objatt.Name, sp.Name, attachmentPt, m_scene.Name); | 1006 | } |
873 | |||
874 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | ||
875 | objatt.HasGroupChanged = false; | ||
876 | bool tainted = false; | ||
877 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) | ||
878 | tainted = true; | ||
879 | |||
880 | // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal | ||
881 | // course of events. If not, then it's probably not worth trying to recover the situation | ||
882 | // since this is more likely to trigger further exceptions and confuse later debugging. If | ||
883 | // exceptions can be thrown in expected error conditions (not NREs) then make this consistent | ||
884 | // since other normal error conditions will simply return false instead. | ||
885 | // This will throw if the attachment fails | ||
886 | try | ||
887 | { | ||
888 | AttachObjectInternal(sp, objatt, attachmentPt, false, false, false); | ||
889 | } | ||
890 | catch (Exception e) | ||
891 | { | ||
892 | m_log.ErrorFormat( | ||
893 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", | ||
894 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); | ||
895 | |||
896 | // Make sure the object doesn't stick around and bail | ||
897 | sp.RemoveAttachment(objatt); | ||
898 | m_scene.DeleteSceneObject(objatt, false); | ||
899 | return null; | ||
900 | } | ||
901 | |||
902 | if (tainted) | ||
903 | objatt.HasGroupChanged = true; | ||
904 | 1007 | ||
905 | if (doc != null) | 1008 | AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append); |
906 | { | 1009 | } |
907 | objatt.LoadScriptState(doc); | 1010 | catch (Exception e) |
908 | objatt.ResetOwnerChangeFlag(); | 1011 | { |
909 | } | 1012 | m_log.ErrorFormat( |
1013 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", | ||
1014 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); | ||
910 | 1015 | ||
911 | // Fire after attach, so we don't get messy perms dialogs | 1016 | // Make sure the object doesn't stick around and bail |
912 | // 4 == AttachedRez | 1017 | sp.RemoveAttachment(objatt); |
913 | objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | 1018 | m_scene.DeleteSceneObject(objatt, false); |
914 | objatt.ResumeScripts(); | 1019 | return null; |
1020 | } | ||
915 | 1021 | ||
916 | // Do this last so that event listeners have access to all the effects of the attachment | 1022 | if (tainted) |
917 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); | 1023 | objatt.HasGroupChanged = true; |
918 | 1024 | ||
919 | return objatt; | 1025 | return objatt; |
920 | } | ||
921 | else | ||
922 | { | ||
923 | m_log.WarnFormat( | ||
924 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", | ||
925 | itemID, sp.Name, attachmentPt); | ||
926 | } | ||
927 | } | ||
928 | |||
929 | return null; | ||
930 | } | 1026 | } |
931 | 1027 | ||
932 | /// <summary> | 1028 | /// <summary> |
@@ -936,7 +1032,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
936 | /// <param name="AttachmentPt"></param> | 1032 | /// <param name="AttachmentPt"></param> |
937 | /// <param name="itemID"></param> | 1033 | /// <param name="itemID"></param> |
938 | /// <param name="att"></param> | 1034 | /// <param name="att"></param> |
939 | private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) | 1035 | private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att, bool append) |
940 | { | 1036 | { |
941 | // m_log.DebugFormat( | 1037 | // m_log.DebugFormat( |
942 | // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", | 1038 | // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", |
@@ -959,12 +1055,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
959 | if (item == null) | 1055 | if (item == null) |
960 | return; | 1056 | return; |
961 | 1057 | ||
962 | bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); | 1058 | int attFlag = append ? 0x80 : 0; |
1059 | bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID); | ||
963 | if (changed && m_scene.AvatarFactory != null) | 1060 | if (changed && m_scene.AvatarFactory != null) |
964 | { | 1061 | { |
965 | // m_log.DebugFormat( | 1062 | if (DebugLevel > 0) |
966 | // "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()", | 1063 | m_log.DebugFormat( |
967 | // sp.Name, att.Name, AttachmentPt); | 1064 | "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()", |
1065 | sp.Name, att.Name, AttachmentPt); | ||
968 | 1066 | ||
969 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | 1067 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); |
970 | } | 1068 | } |
@@ -979,9 +1077,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
979 | if (!Enabled) | 1077 | if (!Enabled) |
980 | return null; | 1078 | return null; |
981 | 1079 | ||
982 | // m_log.DebugFormat( | 1080 | if (DebugLevel > 0) |
983 | // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", | 1081 | m_log.DebugFormat( |
984 | // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); | 1082 | "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", |
1083 | (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); | ||
985 | 1084 | ||
986 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); | 1085 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
987 | 1086 | ||
@@ -1012,9 +1111,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1012 | 1111 | ||
1013 | private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) | 1112 | private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) |
1014 | { | 1113 | { |
1015 | // m_log.DebugFormat( | 1114 | if (DebugLevel > 0) |
1016 | // "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})", | 1115 | m_log.DebugFormat( |
1017 | // objectLocalID, remoteClient.Name, AttachmentPt, silent); | 1116 | "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})", |
1117 | objectLocalID, remoteClient.Name, AttachmentPt, silent); | ||
1018 | 1118 | ||
1019 | if (!Enabled) | 1119 | if (!Enabled) |
1020 | return; | 1120 | return; |
@@ -1043,16 +1143,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1043 | return; | 1143 | return; |
1044 | } | 1144 | } |
1045 | 1145 | ||
1046 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | 1146 | bool append = (AttachmentPt & 0x80) != 0; |
1047 | // be removed when that functionality is implemented in opensim | ||
1048 | AttachmentPt &= 0x7f; | 1147 | AttachmentPt &= 0x7f; |
1049 | 1148 | ||
1050 | // Calls attach with a Zero position | 1149 | // Calls attach with a Zero position |
1051 | if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false)) | 1150 | if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, false, append)) |
1052 | { | 1151 | { |
1053 | // m_log.Debug( | 1152 | if (DebugLevel > 0) |
1054 | // "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId | 1153 | m_log.Debug( |
1055 | // + ", AttachmentPoint: " + AttachmentPt); | 1154 | "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId |
1155 | + ", AttachmentPoint: " + AttachmentPt); | ||
1056 | 1156 | ||
1057 | // Save avatar attachment information | 1157 | // Save avatar attachment information |
1058 | m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); | 1158 | m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); |
@@ -1084,17 +1184,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1084 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); | 1184 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
1085 | if (sp != null) | 1185 | if (sp != null) |
1086 | { | 1186 | { |
1087 | lock (sp.AttachmentsSyncLock) | 1187 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
1188 | |||
1189 | foreach (SceneObjectGroup group in attachments) | ||
1088 | { | 1190 | { |
1089 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | 1191 | if (group.FromItemID == itemID && group.FromItemID != UUID.Zero) |
1090 | |||
1091 | foreach (SceneObjectGroup group in attachments) | ||
1092 | { | 1192 | { |
1093 | if (group.FromItemID == itemID && group.FromItemID != UUID.Zero) | 1193 | DetachSingleAttachmentToInv(sp, group); |
1094 | { | 1194 | return; |
1095 | DetachSingleAttachmentToInv(sp, group); | ||
1096 | return; | ||
1097 | } | ||
1098 | } | 1195 | } |
1099 | } | 1196 | } |
1100 | } | 1197 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 4e9d3f9..1a38619 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | |||
@@ -130,7 +130,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
130 | config.AddConfig("Modules"); | 130 | config.AddConfig("Modules"); |
131 | config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); | 131 | config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); |
132 | 132 | ||
133 | modules.Add(new AttachmentsModule()); | 133 | AttachmentsModule attMod = new AttachmentsModule(); |
134 | attMod.DebugLevel = 1; | ||
135 | modules.Add(attMod); | ||
134 | modules.Add(new BasicInventoryAccessModule()); | 136 | modules.Add(new BasicInventoryAccessModule()); |
135 | } | 137 | } |
136 | 138 | ||
@@ -197,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
197 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); | 199 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); |
198 | 200 | ||
199 | m_numberOfAttachEventsFired = 0; | 201 | m_numberOfAttachEventsFired = 0; |
200 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); | 202 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false); |
201 | 203 | ||
202 | // Check status on scene presence | 204 | // Check status on scene presence |
203 | Assert.That(sp.HasAttachments(), Is.True); | 205 | Assert.That(sp.HasAttachments(), Is.True); |
@@ -228,6 +230,120 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
228 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | 230 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); |
229 | } | 231 | } |
230 | 232 | ||
233 | [Test] | ||
234 | public void TestWearAttachmentFromGround() | ||
235 | { | ||
236 | TestHelpers.InMethod(); | ||
237 | // TestHelpers.EnableLogging(); | ||
238 | |||
239 | Scene scene = CreateTestScene(); | ||
240 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); | ||
241 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); | ||
242 | |||
243 | SceneObjectGroup so2 = SceneHelpers.AddSceneObject(scene, "att2", sp.UUID); | ||
244 | |||
245 | { | ||
246 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID); | ||
247 | |||
248 | m_numberOfAttachEventsFired = 0; | ||
249 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false, false); | ||
250 | |||
251 | // Check status on scene presence | ||
252 | Assert.That(sp.HasAttachments(), Is.True); | ||
253 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
254 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
255 | SceneObjectGroup attSo = attachments[0]; | ||
256 | Assert.That(attSo.Name, Is.EqualTo(so.Name)); | ||
257 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
258 | Assert.That(attSo.IsAttachment); | ||
259 | Assert.That(attSo.UsesPhysics, Is.False); | ||
260 | Assert.That(attSo.IsTemporary, Is.False); | ||
261 | |||
262 | // Check item status | ||
263 | Assert.That( | ||
264 | sp.Appearance.GetAttachpoint(attSo.FromItemID), | ||
265 | Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
266 | |||
267 | InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); | ||
268 | Assert.That(attachmentItem, Is.Not.Null); | ||
269 | Assert.That(attachmentItem.Name, Is.EqualTo(so.Name)); | ||
270 | |||
271 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | ||
272 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); | ||
273 | |||
274 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(2)); | ||
275 | |||
276 | // Check events | ||
277 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
278 | } | ||
279 | |||
280 | // Test wearing a different attachment from the ground. | ||
281 | { | ||
282 | scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false); | ||
283 | |||
284 | // Check status on scene presence | ||
285 | Assert.That(sp.HasAttachments(), Is.True); | ||
286 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
287 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
288 | SceneObjectGroup attSo = attachments[0]; | ||
289 | Assert.That(attSo.Name, Is.EqualTo(so2.Name)); | ||
290 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
291 | Assert.That(attSo.IsAttachment); | ||
292 | Assert.That(attSo.UsesPhysics, Is.False); | ||
293 | Assert.That(attSo.IsTemporary, Is.False); | ||
294 | |||
295 | // Check item status | ||
296 | Assert.That( | ||
297 | sp.Appearance.GetAttachpoint(attSo.FromItemID), | ||
298 | Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
299 | |||
300 | InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); | ||
301 | Assert.That(attachmentItem, Is.Not.Null); | ||
302 | Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); | ||
303 | |||
304 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | ||
305 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); | ||
306 | |||
307 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
308 | |||
309 | // Check events | ||
310 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
311 | } | ||
312 | |||
313 | // Test rewearing an already worn attachment from ground. Nothing should happen. | ||
314 | { | ||
315 | scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false); | ||
316 | |||
317 | // Check status on scene presence | ||
318 | Assert.That(sp.HasAttachments(), Is.True); | ||
319 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
320 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
321 | SceneObjectGroup attSo = attachments[0]; | ||
322 | Assert.That(attSo.Name, Is.EqualTo(so2.Name)); | ||
323 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
324 | Assert.That(attSo.IsAttachment); | ||
325 | Assert.That(attSo.UsesPhysics, Is.False); | ||
326 | Assert.That(attSo.IsTemporary, Is.False); | ||
327 | |||
328 | // Check item status | ||
329 | Assert.That( | ||
330 | sp.Appearance.GetAttachpoint(attSo.FromItemID), | ||
331 | Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
332 | |||
333 | InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); | ||
334 | Assert.That(attachmentItem, Is.Not.Null); | ||
335 | Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); | ||
336 | |||
337 | InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); | ||
338 | Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); | ||
339 | |||
340 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
341 | |||
342 | // Check events | ||
343 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
344 | } | ||
345 | } | ||
346 | |||
231 | /// <summary> | 347 | /// <summary> |
232 | /// Test that we do not attempt to attach an in-world object that someone else is sitting on. | 348 | /// Test that we do not attempt to attach an in-world object that someone else is sitting on. |
233 | /// </summary> | 349 | /// </summary> |
@@ -254,7 +370,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
254 | sp2.AbsolutePosition = new Vector3(0, 0, 0); | 370 | sp2.AbsolutePosition = new Vector3(0, 0, 0); |
255 | sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); | 371 | sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); |
256 | 372 | ||
257 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); | 373 | scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false); |
258 | 374 | ||
259 | Assert.That(sp.HasAttachments(), Is.False); | 375 | Assert.That(sp.HasAttachments(), Is.False); |
260 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | 376 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); |
@@ -275,29 +391,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
275 | 391 | ||
276 | InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); | 392 | InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); |
277 | 393 | ||
278 | m_numberOfAttachEventsFired = 0; | 394 | { |
279 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( | 395 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( |
280 | sp, attItem.ID, (uint)AttachmentPoint.Chest); | 396 | sp, attItem.ID, (uint)AttachmentPoint.Chest); |
281 | 397 | ||
282 | // Check scene presence status | 398 | // Check scene presence status |
283 | Assert.That(sp.HasAttachments(), Is.True); | 399 | Assert.That(sp.HasAttachments(), Is.True); |
284 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | 400 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
285 | Assert.That(attachments.Count, Is.EqualTo(1)); | 401 | Assert.That(attachments.Count, Is.EqualTo(1)); |
286 | SceneObjectGroup attSo = attachments[0]; | 402 | SceneObjectGroup attSo = attachments[0]; |
287 | Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); | 403 | Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); |
288 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); | 404 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); |
289 | Assert.That(attSo.IsAttachment); | 405 | Assert.That(attSo.IsAttachment); |
290 | Assert.That(attSo.UsesPhysics, Is.False); | 406 | Assert.That(attSo.UsesPhysics, Is.False); |
291 | Assert.That(attSo.IsTemporary, Is.False); | 407 | Assert.That(attSo.IsTemporary, Is.False); |
408 | |||
409 | // Check appearance status | ||
410 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
411 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | ||
412 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
413 | |||
414 | // Check events | ||
415 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
416 | } | ||
417 | |||
418 | // Test attaching an already attached attachment | ||
419 | { | ||
420 | scene.AttachmentsModule.RezSingleAttachmentFromInventory( | ||
421 | sp, attItem.ID, (uint)AttachmentPoint.Chest); | ||
292 | 422 | ||
293 | // Check appearance status | 423 | // Check scene presence status |
294 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | 424 | Assert.That(sp.HasAttachments(), Is.True); |
295 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | 425 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
426 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
427 | SceneObjectGroup attSo = attachments[0]; | ||
428 | Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); | ||
429 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); | ||
430 | Assert.That(attSo.IsAttachment); | ||
431 | Assert.That(attSo.UsesPhysics, Is.False); | ||
432 | Assert.That(attSo.IsTemporary, Is.False); | ||
433 | |||
434 | // Check appearance status | ||
435 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
436 | Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); | ||
437 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
438 | |||
439 | // Check events | ||
440 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
441 | } | ||
442 | } | ||
296 | 443 | ||
297 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | 444 | /// <summary> |
445 | /// Test wearing an attachment from inventory, as opposed to explicit choosing the rez point | ||
446 | /// </summary> | ||
447 | [Test] | ||
448 | public void TestWearAttachmentFromInventory() | ||
449 | { | ||
450 | TestHelpers.InMethod(); | ||
451 | // TestHelpers.EnableLogging(); | ||
298 | 452 | ||
299 | // Check events | 453 | Scene scene = CreateTestScene(); |
300 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | 454 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); |
455 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); | ||
456 | |||
457 | InventoryItemBase attItem1 = CreateAttachmentItem(scene, ua1.PrincipalID, "att1", 0x10, 0x20); | ||
458 | InventoryItemBase attItem2 = CreateAttachmentItem(scene, ua1.PrincipalID, "att2", 0x11, 0x21); | ||
459 | |||
460 | { | ||
461 | m_numberOfAttachEventsFired = 0; | ||
462 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem1.ID, (uint)AttachmentPoint.Default); | ||
463 | |||
464 | // default attachment point is currently the left hand. | ||
465 | Assert.That(sp.HasAttachments(), Is.True); | ||
466 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
467 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
468 | SceneObjectGroup attSo = attachments[0]; | ||
469 | Assert.That(attSo.Name, Is.EqualTo(attItem1.Name)); | ||
470 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
471 | Assert.That(attSo.IsAttachment); | ||
472 | |||
473 | // Check appearance status | ||
474 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
475 | Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
476 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
477 | |||
478 | // Check events | ||
479 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); | ||
480 | } | ||
481 | |||
482 | // Test wearing a second attachment at the same position | ||
483 | // Until multiple attachments at one point is implemented, this will remove the first attachment | ||
484 | // This test relies on both attachments having the same default attachment point (in this case LeftHand | ||
485 | // since none other has been set). | ||
486 | { | ||
487 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); | ||
488 | |||
489 | // default attachment point is currently the left hand. | ||
490 | Assert.That(sp.HasAttachments(), Is.True); | ||
491 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
492 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
493 | SceneObjectGroup attSo = attachments[0]; | ||
494 | Assert.That(attSo.Name, Is.EqualTo(attItem2.Name)); | ||
495 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
496 | Assert.That(attSo.IsAttachment); | ||
497 | |||
498 | // Check appearance status | ||
499 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
500 | Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
501 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
502 | |||
503 | // Check events | ||
504 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
505 | } | ||
506 | |||
507 | // Test wearing an already attached attachment | ||
508 | { | ||
509 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); | ||
510 | |||
511 | // default attachment point is currently the left hand. | ||
512 | Assert.That(sp.HasAttachments(), Is.True); | ||
513 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
514 | Assert.That(attachments.Count, Is.EqualTo(1)); | ||
515 | SceneObjectGroup attSo = attachments[0]; | ||
516 | Assert.That(attSo.Name, Is.EqualTo(attItem2.Name)); | ||
517 | Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); | ||
518 | Assert.That(attSo.IsAttachment); | ||
519 | |||
520 | // Check appearance status | ||
521 | Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); | ||
522 | Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); | ||
523 | Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); | ||
524 | |||
525 | // Check events | ||
526 | Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); | ||
527 | } | ||
301 | } | 528 | } |
302 | 529 | ||
303 | /// <summary> | 530 | /// <summary> |
@@ -503,7 +730,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
503 | public void TestRezAttachmentsOnAvatarEntrance() | 730 | public void TestRezAttachmentsOnAvatarEntrance() |
504 | { | 731 | { |
505 | TestHelpers.InMethod(); | 732 | TestHelpers.InMethod(); |
506 | // log4net.Config.XmlConfigurator.Configure(); | 733 | // TestHelpers.EnableLogging(); |
507 | 734 | ||
508 | Scene scene = CreateTestScene(); | 735 | Scene scene = CreateTestScene(); |
509 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); | 736 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); |
@@ -604,7 +831,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
604 | sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); | 831 | sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); |
605 | 832 | ||
606 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); | 833 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); |
607 | ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, ua1.PrincipalID, sh.SceneManager); | 834 | |
835 | AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); | ||
836 | TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); | ||
837 | List<TestClient> destinationTestClients = new List<TestClient>(); | ||
838 | EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); | ||
839 | |||
840 | ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); | ||
608 | beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); | 841 | beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); |
609 | 842 | ||
610 | InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); | 843 | InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); |
@@ -623,7 +856,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
623 | teleportLookAt, | 856 | teleportLookAt, |
624 | (uint)TeleportFlags.ViaLocation); | 857 | (uint)TeleportFlags.ViaLocation); |
625 | 858 | ||
626 | ((TestClient)beforeTeleportSp.ControllingClient).CompleteTeleportClientSide(); | 859 | destinationTestClients[0].CompleteMovement(); |
627 | 860 | ||
628 | // Check attachments have made it into sceneB | 861 | // Check attachments have made it into sceneB |
629 | ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID); | 862 | ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID); |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 7ec2860..bc79944 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -40,6 +40,7 @@ using OpenSim.Region.Framework.Scenes; | |||
40 | using OpenSim.Services.Interfaces; | 40 | using OpenSim.Services.Interfaces; |
41 | 41 | ||
42 | using Mono.Addins; | 42 | using Mono.Addins; |
43 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
43 | 44 | ||
44 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | 45 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory |
45 | { | 46 | { |
@@ -322,6 +323,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
322 | 323 | ||
323 | if (asset != null) | 324 | if (asset != null) |
324 | { | 325 | { |
326 | // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars | ||
327 | asset.ID = asset.FullID.ToString(); | ||
328 | |||
325 | asset.Temporary = false; | 329 | asset.Temporary = false; |
326 | asset.Local = false; | 330 | asset.Local = false; |
327 | m_scene.AssetService.Store(asset); | 331 | m_scene.AssetService.Store(asset); |
@@ -358,7 +362,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
358 | 362 | ||
359 | public void QueueAppearanceSave(UUID agentid) | 363 | public void QueueAppearanceSave(UUID agentid) |
360 | { | 364 | { |
361 | // m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid); | 365 | // m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid); |
362 | 366 | ||
363 | // 10000 ticks per millisecond, 1000 milliseconds per second | 367 | // 10000 ticks per millisecond, 1000 milliseconds per second |
364 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); | 368 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); |
@@ -655,7 +659,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
655 | return; | 659 | return; |
656 | } | 660 | } |
657 | 661 | ||
658 | // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); | 662 | // m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); |
659 | 663 | ||
660 | // This could take awhile since it needs to pull inventory | 664 | // This could take awhile since it needs to pull inventory |
661 | // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape | 665 | // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape |
@@ -664,6 +668,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
664 | // multiple save requests. | 668 | // multiple save requests. |
665 | SetAppearanceAssets(sp.UUID, sp.Appearance); | 669 | SetAppearanceAssets(sp.UUID, sp.Appearance); |
666 | 670 | ||
671 | // List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); | ||
672 | // foreach (AvatarAttachment att in attachments) | ||
673 | // { | ||
674 | // m_log.DebugFormat( | ||
675 | // "[AVFACTORY]: For {0} saving attachment {1} at point {2}", | ||
676 | // sp.Name, att.ItemID, att.AttachPoint); | ||
677 | // } | ||
678 | |||
667 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); | 679 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); |
668 | 680 | ||
669 | // Trigger this here because it's the final step in the set/queue/save process for appearance setting. | 681 | // Trigger this here because it's the final step in the set/queue/save process for appearance setting. |
@@ -674,26 +686,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
674 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) | 686 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) |
675 | { | 687 | { |
676 | IInventoryService invService = m_scene.InventoryService; | 688 | IInventoryService invService = m_scene.InventoryService; |
677 | 689 | bool resetwearable = false; | |
678 | if (invService.GetRootFolder(userID) != null) | 690 | if (invService.GetRootFolder(userID) != null) |
679 | { | 691 | { |
680 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) | 692 | for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) |
681 | { | 693 | { |
682 | for (int j = 0; j < appearance.Wearables[i].Count; j++) | 694 | for (int j = 0; j < appearance.Wearables[i].Count; j++) |
683 | { | 695 | { |
696 | // Check if the default wearables are not set | ||
684 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) | 697 | if (appearance.Wearables[i][j].ItemID == UUID.Zero) |
698 | { | ||
699 | switch ((WearableType) i) | ||
700 | { | ||
701 | case WearableType.Eyes: | ||
702 | case WearableType.Hair: | ||
703 | case WearableType.Shape: | ||
704 | case WearableType.Skin: | ||
705 | //case WearableType.Underpants: | ||
706 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
707 | resetwearable = true; | ||
708 | m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values."); | ||
709 | resetwearable = true; | ||
710 | break; | ||
711 | |||
712 | } | ||
685 | continue; | 713 | continue; |
714 | } | ||
686 | 715 | ||
687 | // Ignore ruth's assets | 716 | // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1 |
688 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) | 717 | if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) |
718 | { | ||
719 | switch ((WearableType)i) | ||
720 | { | ||
721 | case WearableType.Eyes: | ||
722 | case WearableType.Hair: | ||
723 | case WearableType.Shape: | ||
724 | case WearableType.Skin: | ||
725 | //case WearableType.Underpants: | ||
726 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); | ||
727 | |||
728 | m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); | ||
729 | resetwearable = true; | ||
730 | break; | ||
731 | |||
732 | } | ||
689 | continue; | 733 | continue; |
690 | 734 | } | |
735 | |||
691 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); | 736 | InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); |
692 | baseItem = invService.GetItem(baseItem); | 737 | baseItem = invService.GetItem(baseItem); |
693 | 738 | ||
694 | if (baseItem != null) | 739 | if (baseItem != null) |
695 | { | 740 | { |
696 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); | 741 | appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); |
742 | int unmodifiedWearableIndexForClosure = i; | ||
743 | m_scene.AssetService.Get(baseItem.AssetID.ToString(), this, | ||
744 | delegate(string x, object y, AssetBase z) | ||
745 | { | ||
746 | if (z == null) | ||
747 | { | ||
748 | TryAndRepairBrokenWearable( | ||
749 | (WearableType)unmodifiedWearableIndexForClosure, invService, | ||
750 | userID, appearance); | ||
751 | } | ||
752 | }); | ||
697 | } | 753 | } |
698 | else | 754 | else |
699 | { | 755 | { |
@@ -701,17 +757,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
701 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", | 757 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", |
702 | appearance.Wearables[i][j].ItemID, (WearableType)i); | 758 | appearance.Wearables[i][j].ItemID, (WearableType)i); |
703 | 759 | ||
704 | appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); | 760 | TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); |
761 | resetwearable = true; | ||
762 | |||
705 | } | 763 | } |
706 | } | 764 | } |
707 | } | 765 | } |
766 | |||
767 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
768 | if (appearance.Wearables[(int) WearableType.Eyes] == null) | ||
769 | { | ||
770 | m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); | ||
771 | |||
772 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
773 | resetwearable = true; | ||
774 | } | ||
775 | else | ||
776 | { | ||
777 | if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero) | ||
778 | { | ||
779 | m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}", | ||
780 | appearance.Wearables[(int) WearableType.Eyes][0].ItemID, | ||
781 | appearance.Wearables[(int) WearableType.Eyes][0].AssetID); | ||
782 | TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); | ||
783 | resetwearable = true; | ||
784 | |||
785 | } | ||
786 | |||
787 | } | ||
788 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
789 | if (appearance.Wearables[(int)WearableType.Shape] == null) | ||
790 | { | ||
791 | m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape)); | ||
792 | |||
793 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
794 | resetwearable = true; | ||
795 | } | ||
796 | else | ||
797 | { | ||
798 | if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero) | ||
799 | { | ||
800 | m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}", | ||
801 | appearance.Wearables[(int)WearableType.Shape][0].ItemID, | ||
802 | appearance.Wearables[(int)WearableType.Shape][0].AssetID); | ||
803 | TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); | ||
804 | resetwearable = true; | ||
805 | |||
806 | } | ||
807 | |||
808 | } | ||
809 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
810 | if (appearance.Wearables[(int)WearableType.Hair] == null) | ||
811 | { | ||
812 | m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair)); | ||
813 | |||
814 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
815 | resetwearable = true; | ||
816 | } | ||
817 | else | ||
818 | { | ||
819 | if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero) | ||
820 | { | ||
821 | m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}", | ||
822 | appearance.Wearables[(int)WearableType.Hair][0].ItemID, | ||
823 | appearance.Wearables[(int)WearableType.Hair][0].AssetID); | ||
824 | TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); | ||
825 | resetwearable = true; | ||
826 | |||
827 | } | ||
828 | |||
829 | } | ||
830 | // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... | ||
831 | if (appearance.Wearables[(int)WearableType.Skin] == null) | ||
832 | { | ||
833 | m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin)); | ||
834 | |||
835 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
836 | resetwearable = true; | ||
837 | } | ||
838 | else | ||
839 | { | ||
840 | if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero) | ||
841 | { | ||
842 | m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}", | ||
843 | appearance.Wearables[(int)WearableType.Skin][0].ItemID, | ||
844 | appearance.Wearables[(int)WearableType.Skin][0].AssetID); | ||
845 | TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); | ||
846 | resetwearable = true; | ||
847 | |||
848 | } | ||
849 | |||
850 | } | ||
851 | if (resetwearable) | ||
852 | { | ||
853 | ScenePresence presence = null; | ||
854 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
855 | { | ||
856 | presence.ControllingClient.SendWearables(presence.Appearance.Wearables, | ||
857 | presence.Appearance.Serial++); | ||
858 | } | ||
859 | } | ||
860 | |||
708 | } | 861 | } |
709 | else | 862 | else |
710 | { | 863 | { |
711 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); | 864 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); |
712 | } | 865 | } |
713 | } | 866 | } |
867 | private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance) | ||
868 | { | ||
869 | UUID defaultwearable = GetDefaultItem(type); | ||
870 | if (defaultwearable != UUID.Zero) | ||
871 | { | ||
872 | UUID newInvItem = UUID.Random(); | ||
873 | InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) | ||
874 | { | ||
875 | AssetID = | ||
876 | defaultwearable, | ||
877 | AssetType | ||
878 | = | ||
879 | (int) | ||
880 | AssetType | ||
881 | .Bodypart, | ||
882 | CreatorId | ||
883 | = | ||
884 | userID | ||
885 | .ToString | ||
886 | (), | ||
887 | //InvType = (int)InventoryType.Wearable, | ||
888 | |||
889 | Description | ||
890 | = | ||
891 | "Failed Wearable Replacement", | ||
892 | Folder = | ||
893 | invService | ||
894 | .GetFolderForType | ||
895 | (userID, | ||
896 | AssetType | ||
897 | .Bodypart) | ||
898 | .ID, | ||
899 | Flags = (uint) type, | ||
900 | Name = Enum.GetName(typeof (WearableType), type), | ||
901 | BasePermissions = (uint) PermissionMask.Copy, | ||
902 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
903 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
904 | GroupPermissions = (uint) PermissionMask.Copy, | ||
905 | NextPermissions = (uint) PermissionMask.Copy | ||
906 | }; | ||
907 | invService.AddItem(itembase); | ||
908 | UUID LinkInvItem = UUID.Random(); | ||
909 | itembase = new InventoryItemBase(LinkInvItem, userID) | ||
910 | { | ||
911 | AssetID = | ||
912 | newInvItem, | ||
913 | AssetType | ||
914 | = | ||
915 | (int) | ||
916 | AssetType | ||
917 | .Link, | ||
918 | CreatorId | ||
919 | = | ||
920 | userID | ||
921 | .ToString | ||
922 | (), | ||
923 | InvType = (int) InventoryType.Wearable, | ||
924 | |||
925 | Description | ||
926 | = | ||
927 | "Failed Wearable Replacement", | ||
928 | Folder = | ||
929 | invService | ||
930 | .GetFolderForType | ||
931 | (userID, | ||
932 | AssetType | ||
933 | .CurrentOutfitFolder) | ||
934 | .ID, | ||
935 | Flags = (uint) type, | ||
936 | Name = Enum.GetName(typeof (WearableType), type), | ||
937 | BasePermissions = (uint) PermissionMask.Copy, | ||
938 | CurrentPermissions = (uint) PermissionMask.Copy, | ||
939 | EveryOnePermissions = (uint) PermissionMask.Copy, | ||
940 | GroupPermissions = (uint) PermissionMask.Copy, | ||
941 | NextPermissions = (uint) PermissionMask.Copy | ||
942 | }; | ||
943 | invService.AddItem(itembase); | ||
944 | appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); | ||
945 | ScenePresence presence = null; | ||
946 | if (m_scene.TryGetScenePresence(userID, out presence)) | ||
947 | { | ||
948 | m_scene.SendInventoryUpdate(presence.ControllingClient, | ||
949 | invService.GetFolderForType(userID, | ||
950 | AssetType | ||
951 | .CurrentOutfitFolder), | ||
952 | false, true); | ||
953 | } | ||
954 | } | ||
955 | } | ||
956 | private UUID GetDefaultItem(WearableType wearable) | ||
957 | { | ||
958 | // These are ruth | ||
959 | UUID ret = UUID.Zero; | ||
960 | switch (wearable) | ||
961 | { | ||
962 | case WearableType.Eyes: | ||
963 | ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); | ||
964 | break; | ||
965 | case WearableType.Hair: | ||
966 | ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66"); | ||
967 | break; | ||
968 | case WearableType.Pants: | ||
969 | ret = new UUID("00000000-38f9-1111-024e-222222111120"); | ||
970 | break; | ||
971 | case WearableType.Shape: | ||
972 | ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); | ||
973 | break; | ||
974 | case WearableType.Shirt: | ||
975 | ret = new UUID("00000000-38f9-1111-024e-222222111110"); | ||
976 | break; | ||
977 | case WearableType.Skin: | ||
978 | ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb"); | ||
979 | break; | ||
980 | case WearableType.Undershirt: | ||
981 | ret = new UUID("16499ebb-3208-ec27-2def-481881728f47"); | ||
982 | break; | ||
983 | case WearableType.Underpants: | ||
984 | ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d"); | ||
985 | break; | ||
986 | } | ||
714 | 987 | ||
988 | return ret; | ||
989 | } | ||
715 | #endregion | 990 | #endregion |
716 | 991 | ||
717 | #region Client Event Handlers | 992 | #region Client Event Handlers |
@@ -824,7 +1099,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
824 | } | 1099 | } |
825 | 1100 | ||
826 | bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp); | 1101 | bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp); |
827 | outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); | 1102 | outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete"); |
828 | } | 1103 | } |
829 | } | 1104 | } |
830 | } | 1105 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index e21547c..f090e15 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs | |||
@@ -39,7 +39,7 @@ using OpenSim.Tests.Common.Mock; | |||
39 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | 39 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory |
40 | { | 40 | { |
41 | [TestFixture] | 41 | [TestFixture] |
42 | public class AvatarFactoryModuleTests | 42 | public class AvatarFactoryModuleTests : OpenSimTestCase |
43 | { | 43 | { |
44 | /// <summary> | 44 | /// <summary> |
45 | /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. | 45 | /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. |
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 4c3f1cc..174642d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | |||
@@ -256,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
256 | // If camera is moved into client, then camera position can be used | 256 | // If camera is moved into client, then camera position can be used |
257 | // MT: No, it can't, as chat is heard from the avatar position, not | 257 | // MT: No, it can't, as chat is heard from the avatar position, not |
258 | // the camera position. | 258 | // the camera position. |
259 | s.ForEachRootScenePresence( | 259 | s.ForEachScenePresence( |
260 | delegate(ScenePresence presence) | 260 | delegate(ScenePresence presence) |
261 | { | 261 | { |
262 | if (destination != UUID.Zero && presence.UUID != destination) | 262 | if (destination != UUID.Zero && presence.UUID != destination) |
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs index 5ec0ea9..b44a5c9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs | |||
@@ -36,6 +36,7 @@ using OpenSim.Region.Framework.Interfaces; | |||
36 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
37 | using OpenSim.Services.Interfaces; | 37 | using OpenSim.Services.Interfaces; |
38 | using Mono.Addins; | 38 | using Mono.Addins; |
39 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
39 | 40 | ||
40 | namespace OpenSim.Region.CoreModules.Avatar.Friends | 41 | namespace OpenSim.Region.CoreModules.Avatar.Friends |
41 | { | 42 | { |
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs index 7a197f7..961117e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs | |||
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock; | |||
40 | namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests | 40 | namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests |
41 | { | 41 | { |
42 | [TestFixture] | 42 | [TestFixture] |
43 | public class FriendsModuleTests | 43 | public class FriendsModuleTests : OpenSimTestCase |
44 | { | 44 | { |
45 | private FriendsModule m_fm; | 45 | private FriendsModule m_fm; |
46 | private TestScene m_scene; | 46 | private TestScene m_scene; |
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 9fa9be1..fa8c3f3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | |||
@@ -67,9 +67,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
67 | protected Scene m_scene; | 67 | protected Scene m_scene; |
68 | protected IDialogModule m_dialogModule; | 68 | protected IDialogModule m_dialogModule; |
69 | 69 | ||
70 | protected Dictionary<UUID, string> m_capsDict = | ||
71 | new Dictionary<UUID, string>(); | ||
72 | |||
73 | protected IDialogModule DialogModule | 70 | protected IDialogModule DialogModule |
74 | { | 71 | { |
75 | get | 72 | get |
@@ -91,7 +88,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
91 | m_scene.RegisterModuleInterface<IGodsModule>(this); | 88 | m_scene.RegisterModuleInterface<IGodsModule>(this); |
92 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; | 89 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; |
93 | m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; | 90 | m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; |
94 | m_scene.EventManager.OnClientClosed += OnClientClosed; | ||
95 | scene.EventManager.OnIncomingInstantMessage += | 91 | scene.EventManager.OnIncomingInstantMessage += |
96 | OnIncomingInstantMessage; | 92 | OnIncomingInstantMessage; |
97 | } | 93 | } |
@@ -127,15 +123,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
127 | client.OnRequestGodlikePowers -= RequestGodlikePowers; | 123 | client.OnRequestGodlikePowers -= RequestGodlikePowers; |
128 | } | 124 | } |
129 | 125 | ||
130 | private void OnClientClosed(UUID agentID, Scene scene) | ||
131 | { | ||
132 | m_capsDict.Remove(agentID); | ||
133 | } | ||
134 | |||
135 | private void OnRegisterCaps(UUID agentID, Caps caps) | 126 | private void OnRegisterCaps(UUID agentID, Caps caps) |
136 | { | 127 | { |
137 | string uri = "/CAPS/" + UUID.Random(); | 128 | string uri = "/CAPS/" + UUID.Random(); |
138 | m_capsDict[agentID] = uri; | ||
139 | 129 | ||
140 | caps.RegisterHandler("UntrustedSimulatorMessage", | 130 | caps.RegisterHandler("UntrustedSimulatorMessage", |
141 | new RestStreamHandler("POST", uri, | 131 | new RestStreamHandler("POST", uri, |
@@ -288,8 +278,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
288 | if (sp.IsChildAgent) | 278 | if (sp.IsChildAgent) |
289 | return; | 279 | return; |
290 | sp.ControllingClient.Kick(reason); | 280 | sp.ControllingClient.Kick(reason); |
291 | sp.MakeChildAgent(); | 281 | sp.Scene.IncomingCloseAgent(sp.UUID, true); |
292 | sp.ControllingClient.Close(); | ||
293 | } | 282 | } |
294 | 283 | ||
295 | private void OnIncomingInstantMessage(GridInstantMessage msg) | 284 | private void OnIncomingInstantMessage(GridInstantMessage msg) |
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index cc266df..1627f6c 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs | |||
@@ -153,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
153 | if (sp != null && !sp.IsChildAgent) | 153 | if (sp != null && !sp.IsChildAgent) |
154 | { | 154 | { |
155 | // Local message | 155 | // Local message |
156 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); | 156 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); |
157 | 157 | ||
158 | sp.ControllingClient.SendInstantMessage(im); | 158 | sp.ControllingClient.SendInstantMessage(im); |
159 | 159 | ||
@@ -166,14 +166,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
166 | // try child avatar second | 166 | // try child avatar second |
167 | foreach (Scene scene in m_Scenes) | 167 | foreach (Scene scene in m_Scenes) |
168 | { | 168 | { |
169 | //m_log.DebugFormat( | 169 | // m_log.DebugFormat( |
170 | // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); | 170 | // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); |
171 | 171 | ||
172 | ScenePresence sp = scene.GetScenePresence(toAgentID); | 172 | ScenePresence sp = scene.GetScenePresence(toAgentID); |
173 | if (sp != null) | 173 | if (sp != null) |
174 | { | 174 | { |
175 | // Local message | 175 | // Local message |
176 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); | 176 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); |
177 | 177 | ||
178 | sp.ControllingClient.SendInstantMessage(im); | 178 | sp.ControllingClient.SendInstantMessage(im); |
179 | 179 | ||
@@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
183 | } | 183 | } |
184 | } | 184 | } |
185 | 185 | ||
186 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); | 186 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); |
187 | 187 | ||
188 | SendGridInstantMessageViaXMLRPC(im, result); | 188 | SendGridInstantMessageViaXMLRPC(im, result); |
189 | } | 189 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 3a44cc5..2d46276 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs | |||
@@ -189,20 +189,24 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
189 | { | 189 | { |
190 | foreach (GridInstantMessage im in msglist) | 190 | foreach (GridInstantMessage im in msglist) |
191 | { | 191 | { |
192 | // client.SendInstantMessage(im); | 192 | if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) |
193 | 193 | // send it directly or else the item will be given twice | |
194 | // Send through scene event manager so all modules get a chance | 194 | client.SendInstantMessage(im); |
195 | // to look at this message before it gets delivered. | 195 | else |
196 | // | 196 | { |
197 | // Needed for proper state management for stored group | 197 | // Send through scene event manager so all modules get a chance |
198 | // invitations | 198 | // to look at this message before it gets delivered. |
199 | // | 199 | // |
200 | 200 | // Needed for proper state management for stored group | |
201 | im.offline = 1; | 201 | // invitations |
202 | 202 | // | |
203 | Scene s = FindScene(client.AgentId); | 203 | |
204 | if (s != null) | 204 | im.offline = 1; |
205 | s.EventManager.TriggerIncomingInstantMessage(im); | 205 | |
206 | Scene s = FindScene(client.AgentId); | ||
207 | if (s != null) | ||
208 | s.EventManager.TriggerIncomingInstantMessage(im); | ||
209 | } | ||
206 | } | 210 | } |
207 | } | 211 | } |
208 | } | 212 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index dc2b0e0..659b178 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs | |||
@@ -161,7 +161,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
161 | string filePath = "ERROR"; | 161 | string filePath = "ERROR"; |
162 | 162 | ||
163 | List<InventoryFolderBase> folderCandidates | 163 | List<InventoryFolderBase> folderCandidates |
164 | = InventoryArchiveUtils.FindFolderByPath( | 164 | = InventoryArchiveUtils.FindFoldersByPath( |
165 | m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); | 165 | m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); |
166 | 166 | ||
167 | if (folderCandidates.Count == 0) | 167 | if (folderCandidates.Count == 0) |
@@ -296,7 +296,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
296 | // iar name and try to find that instead. | 296 | // iar name and try to find that instead. |
297 | string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); | 297 | string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); |
298 | List<InventoryFolderBase> folderCandidates | 298 | List<InventoryFolderBase> folderCandidates |
299 | = InventoryArchiveUtils.FindFolderByPath( | 299 | = InventoryArchiveUtils.FindFoldersByPath( |
300 | m_scene.InventoryService, m_userInfo.PrincipalID, plainPath); | 300 | m_scene.InventoryService, m_userInfo.PrincipalID, plainPath); |
301 | 301 | ||
302 | if (folderCandidates.Count != 0) | 302 | if (folderCandidates.Count != 0) |
@@ -487,6 +487,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
487 | { | 487 | { |
488 | // m_log.DebugFormat( | 488 | // m_log.DebugFormat( |
489 | // "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); | 489 | // "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); |
490 | |||
491 | if (coa.Objects.Count == 0) | ||
492 | { | ||
493 | m_log.WarnFormat( | ||
494 | "[INVENTORY ARCHIVE READ REQUEST]: Aborting load of coalesced object from asset {0} as it has zero loaded components", | ||
495 | assetId); | ||
496 | return false; | ||
497 | } | ||
490 | 498 | ||
491 | sceneObjects.AddRange(coa.Objects); | 499 | sceneObjects.AddRange(coa.Objects); |
492 | } | 500 | } |
@@ -495,7 +503,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
495 | SceneObjectGroup deserializedObject = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | 503 | SceneObjectGroup deserializedObject = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); |
496 | 504 | ||
497 | if (deserializedObject != null) | 505 | if (deserializedObject != null) |
506 | { | ||
498 | sceneObjects.Add(deserializedObject); | 507 | sceneObjects.Add(deserializedObject); |
508 | } | ||
509 | else | ||
510 | { | ||
511 | m_log.WarnFormat( | ||
512 | "[INVENTORY ARCHIVE READ REQUEST]: Aborting load of object from asset {0} as deserialization failed", | ||
513 | assetId); | ||
514 | |||
515 | return false; | ||
516 | } | ||
499 | } | 517 | } |
500 | 518 | ||
501 | foreach (SceneObjectGroup sog in sceneObjects) | 519 | foreach (SceneObjectGroup sog in sceneObjects) |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index 0d90a15..dbaf2aa 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs | |||
@@ -52,13 +52,82 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
52 | /// <summary> | 52 | /// <summary> |
53 | /// Find a folder given a PATH_DELIMITER delimited path starting from a user's root folder | 53 | /// Find a folder given a PATH_DELIMITER delimited path starting from a user's root folder |
54 | /// </summary> | 54 | /// </summary> |
55 | /// <remarks> | ||
56 | /// This method does not handle paths that contain multiple delimitors | ||
57 | /// | ||
58 | /// FIXME: We have no way of distinguishing folders with the same path | ||
55 | /// | 59 | /// |
60 | /// FIXME: Delimitors which occur in names themselves are not currently escapable. | ||
61 | /// </remarks> | ||
62 | /// <param name="inventoryService"> | ||
63 | /// Inventory service to query | ||
64 | /// </param> | ||
65 | /// <param name="userId"> | ||
66 | /// User id to search | ||
67 | /// </param> | ||
68 | /// <param name="path"> | ||
69 | /// The path to the required folder. | ||
70 | /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. | ||
71 | /// </param> | ||
72 | /// <returns>The folder found. Please note that if there are multiple folders with the same name then an | ||
73 | /// unspecified one will be returned. If no such folder eixsts then null is returned</returns> | ||
74 | public static InventoryFolderBase FindFolderByPath( | ||
75 | IInventoryService inventoryService, UUID userId, string path) | ||
76 | { | ||
77 | List<InventoryFolderBase> folders = FindFoldersByPath(inventoryService, userId, path); | ||
78 | |||
79 | if (folders.Count == 0) | ||
80 | return null; | ||
81 | else | ||
82 | return folders[0]; | ||
83 | } | ||
84 | |||
85 | /// <summary> | ||
86 | /// Find a folder given a PATH_DELIMITER delimited path starting from a given folder | ||
87 | /// </summary> | ||
88 | /// <remarks> | ||
56 | /// This method does not handle paths that contain multiple delimitors | 89 | /// This method does not handle paths that contain multiple delimitors |
57 | /// | 90 | /// |
58 | /// FIXME: We have no way of distinguishing folders with the same path | 91 | /// FIXME: We have no way of distinguishing folders with the same path |
59 | /// | 92 | /// |
60 | /// FIXME: Delimitors which occur in names themselves are not currently escapable. | 93 | /// FIXME: Delimitors which occur in names themselves are not currently escapable. |
94 | /// </remarks> | ||
95 | /// <param name="inventoryService"> | ||
96 | /// Inventory service to query | ||
97 | /// </param> | ||
98 | /// <param name="startFolder"> | ||
99 | /// The folder from which the path starts | ||
100 | /// </param> | ||
101 | /// <param name="path"> | ||
102 | /// The path to the required folder. | ||
103 | /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. | ||
104 | /// </param> | ||
105 | /// <returns>The folder found. Please note that if there are multiple folders with the same name then an | ||
106 | /// unspecified one will be returned. If no such folder eixsts then null is returned</returns> | ||
107 | public static InventoryFolderBase FindFolderByPath( | ||
108 | IInventoryService inventoryService, InventoryFolderBase startFolder, string path) | ||
109 | { | ||
110 | if (null == startFolder) | ||
111 | return null; | ||
112 | |||
113 | List<InventoryFolderBase> folders = FindFoldersByPath(inventoryService, startFolder, path); | ||
114 | |||
115 | if (folders.Count == 0) | ||
116 | return null; | ||
117 | else | ||
118 | return folders[0]; | ||
119 | } | ||
120 | |||
121 | /// <summary> | ||
122 | /// Find a set of folders given a PATH_DELIMITER delimited path starting from a user's root folder | ||
123 | /// </summary> | ||
124 | /// <remarks> | ||
125 | /// This method does not handle paths that contain multiple delimitors | ||
126 | /// | ||
127 | /// FIXME: We have no way of distinguishing folders with the same path | ||
61 | /// | 128 | /// |
129 | /// FIXME: Delimitors which occur in names themselves are not currently escapable. | ||
130 | /// </remarks> | ||
62 | /// <param name="inventoryService"> | 131 | /// <param name="inventoryService"> |
63 | /// Inventory service to query | 132 | /// Inventory service to query |
64 | /// </param> | 133 | /// </param> |
@@ -70,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
70 | /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. | 139 | /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. |
71 | /// </param> | 140 | /// </param> |
72 | /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns> | 141 | /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns> |
73 | public static List<InventoryFolderBase> FindFolderByPath( | 142 | public static List<InventoryFolderBase> FindFoldersByPath( |
74 | IInventoryService inventoryService, UUID userId, string path) | 143 | IInventoryService inventoryService, UUID userId, string path) |
75 | { | 144 | { |
76 | InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); | 145 | InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); |
@@ -78,19 +147,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
78 | if (null == rootFolder) | 147 | if (null == rootFolder) |
79 | return new List<InventoryFolderBase>(); | 148 | return new List<InventoryFolderBase>(); |
80 | 149 | ||
81 | return FindFolderByPath(inventoryService, rootFolder, path); | 150 | return FindFoldersByPath(inventoryService, rootFolder, path); |
82 | } | 151 | } |
83 | 152 | ||
84 | /// <summary> | 153 | /// <summary> |
85 | /// Find a folder given a PATH_DELIMITER delimited path starting from this folder | 154 | /// Find a set of folders given a PATH_DELIMITER delimited path starting from this folder |
86 | /// </summary> | 155 | /// </summary> |
87 | /// | 156 | /// <remarks> |
88 | /// This method does not handle paths that contain multiple delimitors | 157 | /// This method does not handle paths that contain multiple delimitors |
89 | /// | 158 | /// |
90 | /// FIXME: We have no way of distinguishing folders with the same path. | 159 | /// FIXME: We have no way of distinguishing folders with the same path. |
91 | /// | 160 | /// |
92 | /// FIXME: Delimitors which occur in names themselves are not currently escapable. | 161 | /// FIXME: Delimitors which occur in names themselves are not currently escapable. |
93 | /// | 162 | /// </remarks> |
94 | /// <param name="inventoryService"> | 163 | /// <param name="inventoryService"> |
95 | /// Inventory service to query | 164 | /// Inventory service to query |
96 | /// </param> | 165 | /// </param> |
@@ -102,7 +171,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
102 | /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. | 171 | /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. |
103 | /// </param> | 172 | /// </param> |
104 | /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns> | 173 | /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns> |
105 | public static List<InventoryFolderBase> FindFolderByPath( | 174 | public static List<InventoryFolderBase> FindFoldersByPath( |
106 | IInventoryService inventoryService, InventoryFolderBase startFolder, string path) | 175 | IInventoryService inventoryService, InventoryFolderBase startFolder, string path) |
107 | { | 176 | { |
108 | List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>(); | 177 | List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>(); |
@@ -133,12 +202,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
133 | 202 | ||
134 | InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); | 203 | InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); |
135 | 204 | ||
205 | // m_log.DebugFormat( | ||
206 | // "Found {0} folders in {1} for {2}", contents.Folders.Count, startFolder.Name, startFolder.Owner); | ||
207 | |||
136 | foreach (InventoryFolderBase folder in contents.Folders) | 208 | foreach (InventoryFolderBase folder in contents.Folders) |
137 | { | 209 | { |
138 | if (folder.Name == components[0]) | 210 | if (folder.Name == components[0]) |
139 | { | 211 | { |
140 | if (components.Length > 1) | 212 | if (components.Length > 1) |
141 | foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1])); | 213 | foundFolders.AddRange(FindFoldersByPath(inventoryService, folder, components[1])); |
142 | else | 214 | else |
143 | foundFolders.Add(folder); | 215 | foundFolders.Add(folder); |
144 | } | 216 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d0e88f6..4ec8ae7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | |||
@@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
124 | SaveAssets = true; | 124 | SaveAssets = true; |
125 | } | 125 | } |
126 | 126 | ||
127 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | 127 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut) |
128 | { | 128 | { |
129 | Exception reportedException = null; | 129 | Exception reportedException = null; |
130 | bool succeeded = true; | 130 | bool succeeded = true; |
@@ -143,6 +143,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
143 | m_saveStream.Close(); | 143 | m_saveStream.Close(); |
144 | } | 144 | } |
145 | 145 | ||
146 | if (timedOut) | ||
147 | { | ||
148 | succeeded = false; | ||
149 | reportedException = new Exception("Loading assets timed out"); | ||
150 | } | ||
151 | |||
146 | m_module.TriggerInventoryArchiveSaved( | 152 | m_module.TriggerInventoryArchiveSaved( |
147 | m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); | 153 | m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); |
148 | } | 154 | } |
@@ -266,6 +272,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
266 | saveFolderContentsOnly = true; | 272 | saveFolderContentsOnly = true; |
267 | maxComponentIndex--; | 273 | maxComponentIndex--; |
268 | } | 274 | } |
275 | else if (maxComponentIndex == -1) | ||
276 | { | ||
277 | // If the user has just specified "/", then don't save the root "My Inventory" folder. This is | ||
278 | // more intuitive then requiring the user to specify "/*" for this. | ||
279 | saveFolderContentsOnly = true; | ||
280 | } | ||
269 | 281 | ||
270 | m_invPath = String.Empty; | 282 | m_invPath = String.Empty; |
271 | for (int i = 0; i <= maxComponentIndex; i++) | 283 | for (int i = 0; i <= maxComponentIndex; i++) |
@@ -283,7 +295,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
283 | { | 295 | { |
284 | m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); | 296 | m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); |
285 | List<InventoryFolderBase> candidateFolders | 297 | List<InventoryFolderBase> candidateFolders |
286 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); | 298 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, rootFolder, m_invPath); |
287 | if (candidateFolders.Count > 0) | 299 | if (candidateFolders.Count > 0) |
288 | inventoryFolder = candidateFolders[0]; | 300 | inventoryFolder = candidateFolders[0]; |
289 | } | 301 | } |
@@ -350,7 +362,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
350 | { | 362 | { |
351 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); | 363 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); |
352 | 364 | ||
353 | ReceivedAllAssets(new List<UUID>(), new List<UUID>()); | 365 | ReceivedAllAssets(new List<UUID>(), new List<UUID>(), false); |
354 | } | 366 | } |
355 | } | 367 | } |
356 | catch (Exception) | 368 | catch (Exception) |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs index 6eb3605..95f562e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs | |||
@@ -48,125 +48,9 @@ using OpenSim.Tests.Common.Mock; | |||
48 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | 48 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests |
49 | { | 49 | { |
50 | [TestFixture] | 50 | [TestFixture] |
51 | public class PathTests : InventoryArchiveTestCase | 51 | public class InventoryArchiveLoadPathTests : InventoryArchiveTestCase |
52 | { | 52 | { |
53 | /// <summary> | 53 | /// <summary> |
54 | /// Test saving an inventory path to a V0.1 OpenSim Inventory Archive | ||
55 | /// (subject to change since there is no fixed format yet). | ||
56 | /// </summary> | ||
57 | [Test] | ||
58 | public void TestSavePathToIarV0_1() | ||
59 | { | ||
60 | TestHelpers.InMethod(); | ||
61 | // log4net.Config.XmlConfigurator.Configure(); | ||
62 | |||
63 | InventoryArchiverModule archiverModule = new InventoryArchiverModule(); | ||
64 | |||
65 | Scene scene = new SceneHelpers().SetupScene(); | ||
66 | SceneHelpers.SetupSceneModules(scene, archiverModule); | ||
67 | |||
68 | // Create user | ||
69 | string userFirstName = "Jock"; | ||
70 | string userLastName = "Stirrup"; | ||
71 | string userPassword = "troll"; | ||
72 | UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); | ||
73 | UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); | ||
74 | |||
75 | // Create asset | ||
76 | SceneObjectGroup object1; | ||
77 | SceneObjectPart part1; | ||
78 | { | ||
79 | string partName = "My Little Dog Object"; | ||
80 | UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); | ||
81 | PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); | ||
82 | Vector3 groupPosition = new Vector3(10, 20, 30); | ||
83 | Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); | ||
84 | Vector3 offsetPosition = new Vector3(5, 10, 15); | ||
85 | |||
86 | part1 = new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition); | ||
87 | part1.Name = partName; | ||
88 | |||
89 | object1 = new SceneObjectGroup(part1); | ||
90 | scene.AddNewSceneObject(object1, false); | ||
91 | } | ||
92 | |||
93 | UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); | ||
94 | AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); | ||
95 | scene.AssetService.Store(asset1); | ||
96 | |||
97 | // Create item | ||
98 | UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); | ||
99 | InventoryItemBase item1 = new InventoryItemBase(); | ||
100 | item1.Name = "My Little Dog"; | ||
101 | item1.AssetID = asset1.FullID; | ||
102 | item1.ID = item1Id; | ||
103 | InventoryFolderBase objsFolder | ||
104 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; | ||
105 | item1.Folder = objsFolder.ID; | ||
106 | scene.AddInventoryItem(item1); | ||
107 | |||
108 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
109 | archiverModule.OnInventoryArchiveSaved += SaveCompleted; | ||
110 | |||
111 | // Test saving a particular path | ||
112 | mre.Reset(); | ||
113 | archiverModule.ArchiveInventory( | ||
114 | Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); | ||
115 | mre.WaitOne(60000, false); | ||
116 | |||
117 | byte[] archive = archiveWriteStream.ToArray(); | ||
118 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
119 | TarArchiveReader tar = new TarArchiveReader(archiveReadStream); | ||
120 | |||
121 | //bool gotControlFile = false; | ||
122 | bool gotObject1File = false; | ||
123 | //bool gotObject2File = false; | ||
124 | string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); | ||
125 | string expectedObject1FilePath = string.Format( | ||
126 | "{0}{1}{2}", | ||
127 | ArchiveConstants.INVENTORY_PATH, | ||
128 | InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder), | ||
129 | expectedObject1FileName); | ||
130 | |||
131 | string filePath; | ||
132 | TarArchiveReader.TarEntryType tarEntryType; | ||
133 | |||
134 | // Console.WriteLine("Reading archive"); | ||
135 | |||
136 | while (tar.ReadEntry(out filePath, out tarEntryType) != null) | ||
137 | { | ||
138 | // Console.WriteLine("Got {0}", filePath); | ||
139 | |||
140 | // if (ArchiveConstants.CONTROL_FILE_PATH == filePath) | ||
141 | // { | ||
142 | // gotControlFile = true; | ||
143 | // } | ||
144 | |||
145 | if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) | ||
146 | { | ||
147 | // string fileName = filePath.Remove(0, "Objects/".Length); | ||
148 | // | ||
149 | // if (fileName.StartsWith(part1.Name)) | ||
150 | // { | ||
151 | Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); | ||
152 | gotObject1File = true; | ||
153 | // } | ||
154 | // else if (fileName.StartsWith(part2.Name)) | ||
155 | // { | ||
156 | // Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); | ||
157 | // gotObject2File = true; | ||
158 | // } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | // Assert.That(gotControlFile, Is.True, "No control file in archive"); | ||
163 | Assert.That(gotObject1File, Is.True, "No item1 file in archive"); | ||
164 | // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); | ||
165 | |||
166 | // TODO: Test presence of more files and contents of files. | ||
167 | } | ||
168 | |||
169 | /// <summary> | ||
170 | /// Test loading an IAR to various different inventory paths. | 54 | /// Test loading an IAR to various different inventory paths. |
171 | /// </summary> | 55 | /// </summary> |
172 | [Test] | 56 | [Test] |
@@ -193,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
193 | Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); | 77 | Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); |
194 | 78 | ||
195 | // Now try loading to a root child folder | 79 | // Now try loading to a root child folder |
196 | UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); | 80 | UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false); |
197 | MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); | 81 | MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); |
198 | archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); | 82 | archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); |
199 | 83 | ||
@@ -202,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
202 | Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); | 86 | Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); |
203 | 87 | ||
204 | // Now try loading to a more deeply nested folder | 88 | // Now try loading to a more deeply nested folder |
205 | UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); | 89 | UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC", false); |
206 | archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); | 90 | archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); |
207 | archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); | 91 | archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); |
208 | 92 | ||
@@ -287,7 +171,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
287 | item1.AssetID = asset1.FullID; | 171 | item1.AssetID = asset1.FullID; |
288 | item1.ID = item1Id; | 172 | item1.ID = item1Id; |
289 | InventoryFolderBase objsFolder | 173 | InventoryFolderBase objsFolder |
290 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; | 174 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0]; |
291 | item1.Folder = objsFolder.ID; | 175 | item1.Folder = objsFolder.ID; |
292 | scene.AddInventoryItem(item1); | 176 | scene.AddInventoryItem(item1); |
293 | 177 | ||
@@ -351,12 +235,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
351 | foldersCreated, nodesLoaded); | 235 | foldersCreated, nodesLoaded); |
352 | 236 | ||
353 | List<InventoryFolderBase> folder1Candidates | 237 | List<InventoryFolderBase> folder1Candidates |
354 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); | 238 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); |
355 | Assert.That(folder1Candidates.Count, Is.EqualTo(1)); | 239 | Assert.That(folder1Candidates.Count, Is.EqualTo(1)); |
356 | 240 | ||
357 | InventoryFolderBase folder1 = folder1Candidates[0]; | 241 | InventoryFolderBase folder1 = folder1Candidates[0]; |
358 | List<InventoryFolderBase> folder2aCandidates | 242 | List<InventoryFolderBase> folder2aCandidates |
359 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); | 243 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); |
360 | Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); | 244 | Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); |
361 | } | 245 | } |
362 | 246 | ||
@@ -368,17 +252,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
368 | foldersCreated, nodesLoaded); | 252 | foldersCreated, nodesLoaded); |
369 | 253 | ||
370 | List<InventoryFolderBase> folder1Candidates | 254 | List<InventoryFolderBase> folder1Candidates |
371 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); | 255 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); |
372 | Assert.That(folder1Candidates.Count, Is.EqualTo(1)); | 256 | Assert.That(folder1Candidates.Count, Is.EqualTo(1)); |
373 | 257 | ||
374 | InventoryFolderBase folder1 = folder1Candidates[0]; | 258 | InventoryFolderBase folder1 = folder1Candidates[0]; |
375 | 259 | ||
376 | List<InventoryFolderBase> folder2aCandidates | 260 | List<InventoryFolderBase> folder2aCandidates |
377 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); | 261 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); |
378 | Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); | 262 | Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); |
379 | 263 | ||
380 | List<InventoryFolderBase> folder2bCandidates | 264 | List<InventoryFolderBase> folder2bCandidates |
381 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2bName); | 265 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName); |
382 | Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); | 266 | Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); |
383 | } | 267 | } |
384 | } | 268 | } |
@@ -401,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
401 | 285 | ||
402 | InventoryFolderBase folder1 | 286 | InventoryFolderBase folder1 |
403 | = UserInventoryHelpers.CreateInventoryFolder( | 287 | = UserInventoryHelpers.CreateInventoryFolder( |
404 | scene.InventoryService, ua1.PrincipalID, folder1ExistingName); | 288 | scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); |
405 | 289 | ||
406 | string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); | 290 | string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); |
407 | string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); | 291 | string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); |
@@ -414,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
414 | new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); | 298 | new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); |
415 | 299 | ||
416 | List<InventoryFolderBase> folder1PostCandidates | 300 | List<InventoryFolderBase> folder1PostCandidates |
417 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); | 301 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); |
418 | Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); | 302 | Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); |
419 | 303 | ||
420 | // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. | 304 | // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. |
@@ -430,7 +314,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
430 | // Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); | 314 | // Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); |
431 | 315 | ||
432 | List<InventoryFolderBase> folder2PostCandidates | 316 | List<InventoryFolderBase> folder2PostCandidates |
433 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b"); | 317 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b"); |
434 | Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); | 318 | Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); |
435 | } | 319 | } |
436 | 320 | ||
@@ -452,7 +336,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
452 | 336 | ||
453 | InventoryFolderBase folder1 | 337 | InventoryFolderBase folder1 |
454 | = UserInventoryHelpers.CreateInventoryFolder( | 338 | = UserInventoryHelpers.CreateInventoryFolder( |
455 | scene.InventoryService, ua1.PrincipalID, folder1ExistingName); | 339 | scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); |
456 | 340 | ||
457 | string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); | 341 | string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); |
458 | string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); | 342 | string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); |
@@ -465,13 +349,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
465 | new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); | 349 | new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); |
466 | 350 | ||
467 | List<InventoryFolderBase> folder1PostCandidates | 351 | List<InventoryFolderBase> folder1PostCandidates |
468 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); | 352 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); |
469 | Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); | 353 | Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); |
470 | Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); | 354 | Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); |
471 | 355 | ||
472 | List<InventoryFolderBase> folder2PostCandidates | 356 | List<InventoryFolderBase> folder2PostCandidates |
473 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b"); | 357 | = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b"); |
474 | Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); | 358 | Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); |
475 | } | 359 | } |
476 | } | 360 | } |
477 | } \ No newline at end of file | 361 | } |
362 | |||
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs new file mode 100644 index 0000000..1b521fc --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs | |||
@@ -0,0 +1,194 @@ | |||
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 NUnit.Framework; | ||
34 | using OpenMetaverse; | ||
35 | using OpenSim.Data; | ||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Framework.Serialization; | ||
38 | using OpenSim.Framework.Serialization.External; | ||
39 | using OpenSim.Framework.Communications; | ||
40 | using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; | ||
41 | using OpenSim.Region.CoreModules.World.Serialiser; | ||
42 | using OpenSim.Region.Framework.Scenes; | ||
43 | using OpenSim.Region.Framework.Scenes.Serialization; | ||
44 | using OpenSim.Services.Interfaces; | ||
45 | using OpenSim.Tests.Common; | ||
46 | using OpenSim.Tests.Common.Mock; | ||
47 | |||
48 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | ||
49 | { | ||
50 | [TestFixture] | ||
51 | public class InventoryArchiveLoadTests : InventoryArchiveTestCase | ||
52 | { | ||
53 | protected TestScene m_scene; | ||
54 | protected InventoryArchiverModule m_archiverModule; | ||
55 | |||
56 | [SetUp] | ||
57 | public override void SetUp() | ||
58 | { | ||
59 | base.SetUp(); | ||
60 | |||
61 | SerialiserModule serialiserModule = new SerialiserModule(); | ||
62 | m_archiverModule = new InventoryArchiverModule(); | ||
63 | |||
64 | m_scene = new SceneHelpers().SetupScene(); | ||
65 | SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); | ||
66 | } | ||
67 | |||
68 | [Test] | ||
69 | public void TestLoadCoalesecedItem() | ||
70 | { | ||
71 | TestHelpers.InMethod(); | ||
72 | // TestHelpers.EnableLogging(); | ||
73 | |||
74 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); | ||
75 | m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); | ||
76 | |||
77 | InventoryItemBase coaItem | ||
78 | = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); | ||
79 | |||
80 | Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); | ||
81 | |||
82 | string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); | ||
83 | |||
84 | CoalescedSceneObjects coa; | ||
85 | bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); | ||
86 | |||
87 | Assert.That(readResult, Is.True); | ||
88 | Assert.That(coa.Count, Is.EqualTo(2)); | ||
89 | |||
90 | List<SceneObjectGroup> coaObjects = coa.Objects; | ||
91 | Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); | ||
92 | Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); | ||
93 | |||
94 | Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); | ||
95 | Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); | ||
96 | } | ||
97 | |||
98 | /// <summary> | ||
99 | /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized | ||
100 | /// objects. | ||
101 | /// </summary> | ||
102 | [Test] | ||
103 | public void TestLoadIarCreatorAccountPresent() | ||
104 | { | ||
105 | TestHelpers.InMethod(); | ||
106 | // log4net.Config.XmlConfigurator.Configure(); | ||
107 | |||
108 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); | ||
109 | |||
110 | m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); | ||
111 | InventoryItemBase foundItem1 | ||
112 | = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name); | ||
113 | |||
114 | Assert.That( | ||
115 | foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()), | ||
116 | "Loaded item non-uuid creator doesn't match original"); | ||
117 | Assert.That( | ||
118 | foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID), | ||
119 | "Loaded item uuid creator doesn't match original"); | ||
120 | Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID), | ||
121 | "Loaded item owner doesn't match inventory reciever"); | ||
122 | |||
123 | AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); | ||
124 | string xmlData = Utils.BytesToString(asset1.Data); | ||
125 | SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | ||
126 | |||
127 | Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); | ||
128 | } | ||
129 | |||
130 | // /// <summary> | ||
131 | // /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where | ||
132 | // /// an account exists with the same name as the creator, though not the same id. | ||
133 | // /// </summary> | ||
134 | // [Test] | ||
135 | // public void TestLoadIarV0_1SameNameCreator() | ||
136 | // { | ||
137 | // TestHelpers.InMethod(); | ||
138 | // TestHelpers.EnableLogging(); | ||
139 | // | ||
140 | // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); | ||
141 | // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); | ||
142 | // | ||
143 | // m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); | ||
144 | // InventoryItemBase foundItem1 | ||
145 | // = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); | ||
146 | // | ||
147 | // Assert.That( | ||
148 | // foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), | ||
149 | // "Loaded item non-uuid creator doesn't match original"); | ||
150 | // Assert.That( | ||
151 | // foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), | ||
152 | // "Loaded item uuid creator doesn't match original"); | ||
153 | // Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), | ||
154 | // "Loaded item owner doesn't match inventory reciever"); | ||
155 | // | ||
156 | // AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); | ||
157 | // string xmlData = Utils.BytesToString(asset1.Data); | ||
158 | // SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | ||
159 | // | ||
160 | // Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); | ||
161 | // } | ||
162 | |||
163 | /// <summary> | ||
164 | /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where | ||
165 | /// the creator or an account with the creator's name does not exist within the system. | ||
166 | /// </summary> | ||
167 | [Test] | ||
168 | public void TestLoadIarV0_1AbsentCreator() | ||
169 | { | ||
170 | TestHelpers.InMethod(); | ||
171 | // log4net.Config.XmlConfigurator.Configure(); | ||
172 | |||
173 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); | ||
174 | m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); | ||
175 | |||
176 | InventoryItemBase foundItem1 | ||
177 | = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); | ||
178 | |||
179 | Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); | ||
180 | Assert.That( | ||
181 | foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()), | ||
182 | "Loaded item non-uuid creator doesn't match that of the loading user"); | ||
183 | Assert.That( | ||
184 | foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID), | ||
185 | "Loaded item uuid creator doesn't match that of the loading user"); | ||
186 | |||
187 | AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); | ||
188 | string xmlData = Utils.BytesToString(asset1.Data); | ||
189 | SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | ||
190 | |||
191 | Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); | ||
192 | } | ||
193 | } | ||
194 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs index 06f6e49..5e7e24c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs | |||
@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock; | |||
48 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | 48 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests |
49 | { | 49 | { |
50 | [TestFixture] | 50 | [TestFixture] |
51 | public class InventoryArchiverTests : InventoryArchiveTestCase | 51 | public class InventoryArchiveSaveTests : InventoryArchiveTestCase |
52 | { | 52 | { |
53 | protected TestScene m_scene; | 53 | protected TestScene m_scene; |
54 | protected InventoryArchiverModule m_archiverModule; | 54 | protected InventoryArchiverModule m_archiverModule; |
@@ -64,36 +64,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
64 | m_scene = new SceneHelpers().SetupScene(); | 64 | m_scene = new SceneHelpers().SetupScene(); |
65 | SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); | 65 | SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); |
66 | } | 66 | } |
67 | |||
68 | [Test] | ||
69 | public void TestLoadCoalesecedItem() | ||
70 | { | ||
71 | TestHelpers.InMethod(); | ||
72 | // TestHelpers.EnableLogging(); | ||
73 | |||
74 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); | ||
75 | m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); | ||
76 | |||
77 | InventoryItemBase coaItem | ||
78 | = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); | ||
79 | |||
80 | Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); | ||
81 | |||
82 | string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); | ||
83 | |||
84 | CoalescedSceneObjects coa; | ||
85 | bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); | ||
86 | |||
87 | Assert.That(readResult, Is.True); | ||
88 | Assert.That(coa.Count, Is.EqualTo(2)); | ||
89 | |||
90 | List<SceneObjectGroup> coaObjects = coa.Objects; | ||
91 | Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); | ||
92 | Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); | ||
93 | |||
94 | Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); | ||
95 | Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); | ||
96 | } | ||
97 | 67 | ||
98 | /// <summary> | 68 | /// <summary> |
99 | /// Test that the IAR has the required files in the right order. | 69 | /// Test that the IAR has the required files in the right order. |
@@ -121,6 +91,139 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
121 | 91 | ||
122 | Assert.That(iarr.ControlFileLoaded, Is.True); | 92 | Assert.That(iarr.ControlFileLoaded, Is.True); |
123 | } | 93 | } |
94 | |||
95 | [Test] | ||
96 | public void TestSaveRootFolderToIar() | ||
97 | { | ||
98 | TestHelpers.InMethod(); | ||
99 | // TestHelpers.EnableLogging(); | ||
100 | |||
101 | string userFirstName = "Jock"; | ||
102 | string userLastName = "Stirrup"; | ||
103 | string userPassword = "troll"; | ||
104 | UUID userId = TestHelpers.ParseTail(0x20); | ||
105 | |||
106 | UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); | ||
107 | |||
108 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
109 | m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; | ||
110 | |||
111 | mre.Reset(); | ||
112 | m_archiverModule.ArchiveInventory( | ||
113 | Guid.NewGuid(), userFirstName, userLastName, "/", userPassword, archiveWriteStream); | ||
114 | mre.WaitOne(60000, false); | ||
115 | |||
116 | // Test created iar | ||
117 | byte[] archive = archiveWriteStream.ToArray(); | ||
118 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
119 | TarArchiveReader tar = new TarArchiveReader(archiveReadStream); | ||
120 | |||
121 | // InventoryArchiveUtils. | ||
122 | bool gotObjectsFolder = false; | ||
123 | |||
124 | string objectsFolderName | ||
125 | = string.Format( | ||
126 | "{0}{1}", | ||
127 | ArchiveConstants.INVENTORY_PATH, | ||
128 | InventoryArchiveWriteRequest.CreateArchiveFolderName( | ||
129 | UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects"))); | ||
130 | |||
131 | string filePath; | ||
132 | TarArchiveReader.TarEntryType tarEntryType; | ||
133 | |||
134 | while (tar.ReadEntry(out filePath, out tarEntryType) != null) | ||
135 | { | ||
136 | // Console.WriteLine("Got {0}", filePath); | ||
137 | |||
138 | // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory() | ||
139 | // XXX: But really we need to stop all that stuff being created in tests or check for such folders | ||
140 | // more thoroughly | ||
141 | if (filePath == objectsFolderName) | ||
142 | gotObjectsFolder = true; | ||
143 | } | ||
144 | |||
145 | Assert.That(gotObjectsFolder, Is.True); | ||
146 | } | ||
147 | |||
148 | [Test] | ||
149 | public void TestSaveNonRootFolderToIar() | ||
150 | { | ||
151 | TestHelpers.InMethod(); | ||
152 | // TestHelpers.EnableLogging(); | ||
153 | |||
154 | string userFirstName = "Jock"; | ||
155 | string userLastName = "Stirrup"; | ||
156 | string userPassword = "troll"; | ||
157 | UUID userId = TestHelpers.ParseTail(0x20); | ||
158 | |||
159 | UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); | ||
160 | |||
161 | // Create base folder | ||
162 | InventoryFolderBase f1 | ||
163 | = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true); | ||
164 | |||
165 | // Create item1 | ||
166 | SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5); | ||
167 | InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1"); | ||
168 | |||
169 | // Create embedded folder | ||
170 | InventoryFolderBase f1_1 | ||
171 | = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true); | ||
172 | |||
173 | // Create embedded item | ||
174 | SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6); | ||
175 | InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1"); | ||
176 | |||
177 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
178 | m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; | ||
179 | |||
180 | mre.Reset(); | ||
181 | m_archiverModule.ArchiveInventory( | ||
182 | Guid.NewGuid(), userFirstName, userLastName, "f1", userPassword, archiveWriteStream); | ||
183 | mre.WaitOne(60000, false); | ||
184 | |||
185 | // Test created iar | ||
186 | byte[] archive = archiveWriteStream.ToArray(); | ||
187 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
188 | TarArchiveReader tar = new TarArchiveReader(archiveReadStream); | ||
189 | |||
190 | // InventoryArchiveUtils. | ||
191 | bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false; | ||
192 | |||
193 | string f1FileName | ||
194 | = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1)); | ||
195 | string f1_1FileName | ||
196 | = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1)); | ||
197 | string so1FileName | ||
198 | = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1)); | ||
199 | string so2FileName | ||
200 | = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2)); | ||
201 | |||
202 | string filePath; | ||
203 | TarArchiveReader.TarEntryType tarEntryType; | ||
204 | |||
205 | while (tar.ReadEntry(out filePath, out tarEntryType) != null) | ||
206 | { | ||
207 | // Console.WriteLine("Got {0}", filePath); | ||
208 | |||
209 | if (filePath == f1FileName) | ||
210 | gotf1 = true; | ||
211 | else if (filePath == f1_1FileName) | ||
212 | gotf1_1 = true; | ||
213 | else if (filePath == so1FileName) | ||
214 | gotso1 = true; | ||
215 | else if (filePath == so2FileName) | ||
216 | gotso2 = true; | ||
217 | } | ||
218 | |||
219 | // Assert.That(gotControlFile, Is.True, "No control file in archive"); | ||
220 | Assert.That(gotf1, Is.True); | ||
221 | Assert.That(gotf1_1, Is.True); | ||
222 | Assert.That(gotso1, Is.True); | ||
223 | Assert.That(gotso2, Is.True); | ||
224 | |||
225 | // TODO: Test presence of more files and contents of files. | ||
226 | } | ||
124 | 227 | ||
125 | /// <summary> | 228 | /// <summary> |
126 | /// Test saving a single inventory item to an IAR | 229 | /// Test saving a single inventory item to an IAR |
@@ -155,7 +258,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
155 | item1.AssetID = asset1.FullID; | 258 | item1.AssetID = asset1.FullID; |
156 | item1.ID = item1Id; | 259 | item1.ID = item1Id; |
157 | InventoryFolderBase objsFolder | 260 | InventoryFolderBase objsFolder |
158 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; | 261 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; |
159 | item1.Folder = objsFolder.ID; | 262 | item1.Folder = objsFolder.ID; |
160 | m_scene.AddInventoryItem(item1); | 263 | m_scene.AddInventoryItem(item1); |
161 | 264 | ||
@@ -250,7 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
250 | item1.AssetID = asset1.FullID; | 353 | item1.AssetID = asset1.FullID; |
251 | item1.ID = item1Id; | 354 | item1.ID = item1Id; |
252 | InventoryFolderBase objsFolder | 355 | InventoryFolderBase objsFolder |
253 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; | 356 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; |
254 | item1.Folder = objsFolder.ID; | 357 | item1.Folder = objsFolder.ID; |
255 | m_scene.AddInventoryItem(item1); | 358 | m_scene.AddInventoryItem(item1); |
256 | 359 | ||
@@ -317,101 +420,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
317 | 420 | ||
318 | // TODO: Test presence of more files and contents of files. | 421 | // TODO: Test presence of more files and contents of files. |
319 | } | 422 | } |
320 | |||
321 | /// <summary> | ||
322 | /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized | ||
323 | /// objects. | ||
324 | /// </summary> | ||
325 | [Test] | ||
326 | public void TestLoadIarCreatorAccountPresent() | ||
327 | { | ||
328 | TestHelpers.InMethod(); | ||
329 | // log4net.Config.XmlConfigurator.Configure(); | ||
330 | |||
331 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); | ||
332 | |||
333 | m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); | ||
334 | InventoryItemBase foundItem1 | ||
335 | = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name); | ||
336 | |||
337 | Assert.That( | ||
338 | foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()), | ||
339 | "Loaded item non-uuid creator doesn't match original"); | ||
340 | Assert.That( | ||
341 | foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID), | ||
342 | "Loaded item uuid creator doesn't match original"); | ||
343 | Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID), | ||
344 | "Loaded item owner doesn't match inventory reciever"); | ||
345 | |||
346 | AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); | ||
347 | string xmlData = Utils.BytesToString(asset1.Data); | ||
348 | SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | ||
349 | |||
350 | Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); | ||
351 | } | ||
352 | |||
353 | // /// <summary> | ||
354 | // /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where | ||
355 | // /// an account exists with the same name as the creator, though not the same id. | ||
356 | // /// </summary> | ||
357 | // [Test] | ||
358 | // public void TestLoadIarV0_1SameNameCreator() | ||
359 | // { | ||
360 | // TestHelpers.InMethod(); | ||
361 | // TestHelpers.EnableLogging(); | ||
362 | // | ||
363 | // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); | ||
364 | // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); | ||
365 | // | ||
366 | // m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); | ||
367 | // InventoryItemBase foundItem1 | ||
368 | // = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); | ||
369 | // | ||
370 | // Assert.That( | ||
371 | // foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), | ||
372 | // "Loaded item non-uuid creator doesn't match original"); | ||
373 | // Assert.That( | ||
374 | // foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), | ||
375 | // "Loaded item uuid creator doesn't match original"); | ||
376 | // Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), | ||
377 | // "Loaded item owner doesn't match inventory reciever"); | ||
378 | // | ||
379 | // AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); | ||
380 | // string xmlData = Utils.BytesToString(asset1.Data); | ||
381 | // SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | ||
382 | // | ||
383 | // Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); | ||
384 | // } | ||
385 | |||
386 | /// <summary> | ||
387 | /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where | ||
388 | /// the creator or an account with the creator's name does not exist within the system. | ||
389 | /// </summary> | ||
390 | [Test] | ||
391 | public void TestLoadIarV0_1AbsentCreator() | ||
392 | { | ||
393 | TestHelpers.InMethod(); | ||
394 | // log4net.Config.XmlConfigurator.Configure(); | ||
395 | |||
396 | UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); | ||
397 | m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); | ||
398 | |||
399 | InventoryItemBase foundItem1 | ||
400 | = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); | ||
401 | |||
402 | Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); | ||
403 | Assert.That( | ||
404 | foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()), | ||
405 | "Loaded item non-uuid creator doesn't match that of the loading user"); | ||
406 | Assert.That( | ||
407 | foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID), | ||
408 | "Loaded item uuid creator doesn't match that of the loading user"); | ||
409 | |||
410 | AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); | ||
411 | string xmlData = Utils.BytesToString(asset1.Data); | ||
412 | SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); | ||
413 | |||
414 | Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); | ||
415 | } | ||
416 | } | 423 | } |
417 | } \ No newline at end of file | 424 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 4cfa33d..ae58dfd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | |||
@@ -316,76 +316,74 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
316 | } | 316 | } |
317 | } | 317 | } |
318 | 318 | ||
319 | // Disabled for now as it looks like http://opensimulator.org/mantis/view.php?id=6311 was fixed by fixes | 319 | // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name> |
320 | // to inventory folder versioning allowing the viewer to move the received folder itself as happens on the | 320 | // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be |
321 | // LL grid. Doing it again server-side then wrongly does a second create and move | 321 | // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet |
322 | // // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name> | 322 | // happening, possibly because we are not sending the correct inventory update messages with the correct |
323 | // // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis | 323 | // transaction IDs |
324 | // // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously | 324 | else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) |
325 | // // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. | 325 | { |
326 | // else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) | 326 | UUID destinationFolderID = UUID.Zero; |
327 | // { | 327 | |
328 | // UUID destinationFolderID = UUID.Zero; | 328 | if (im.binaryBucket != null && im.binaryBucket.Length >= 16) |
329 | // | 329 | { |
330 | // if (im.binaryBucket != null && im.binaryBucket.Length >= 16) | 330 | destinationFolderID = new UUID(im.binaryBucket, 0); |
331 | // { | 331 | } |
332 | // destinationFolderID = new UUID(im.binaryBucket, 0); | 332 | |
333 | // } | 333 | if (destinationFolderID != UUID.Zero) |
334 | // | 334 | { |
335 | // if (destinationFolderID != UUID.Zero) | 335 | InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); |
336 | // { | 336 | if (destinationFolder == null) |
337 | // InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); | 337 | { |
338 | // if (destinationFolder == null) | 338 | m_log.WarnFormat( |
339 | // { | 339 | "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", |
340 | // m_log.WarnFormat( | 340 | client.Name, scene.Name, destinationFolderID); |
341 | // "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", | 341 | |
342 | // client.Name, scene.Name, destinationFolderID); | 342 | return; |
343 | // | 343 | } |
344 | // return; | 344 | |
345 | // } | 345 | IInventoryService invService = scene.InventoryService; |
346 | // | 346 | |
347 | // IInventoryService invService = scene.InventoryService; | 347 | UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip |
348 | // | 348 | |
349 | // UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip | 349 | InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); |
350 | // | 350 | item = invService.GetItem(item); |
351 | // InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); | 351 | InventoryFolderBase folder = null; |
352 | // item = invService.GetItem(item); | 352 | UUID? previousParentFolderID = null; |
353 | // InventoryFolderBase folder = null; | 353 | |
354 | // UUID? previousParentFolderID = null; | 354 | if (item != null) // It's an item |
355 | // | 355 | { |
356 | // if (item != null) // It's an item | 356 | previousParentFolderID = item.Folder; |
357 | // { | 357 | item.Folder = destinationFolderID; |
358 | // previousParentFolderID = item.Folder; | 358 | |
359 | // item.Folder = destinationFolderID; | 359 | invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); |
360 | // | 360 | scene.AddInventoryItem(client, item); |
361 | // invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); | 361 | } |
362 | // scene.AddInventoryItem(client, item); | 362 | else |
363 | // } | 363 | { |
364 | // else | 364 | folder = new InventoryFolderBase(inventoryID, client.AgentId); |
365 | // { | 365 | folder = invService.GetFolder(folder); |
366 | // folder = new InventoryFolderBase(inventoryID, client.AgentId); | 366 | |
367 | // folder = invService.GetFolder(folder); | 367 | if (folder != null) // It's a folder |
368 | // | 368 | { |
369 | // if (folder != null) // It's a folder | 369 | previousParentFolderID = folder.ParentID; |
370 | // { | 370 | folder.ParentID = destinationFolderID; |
371 | // previousParentFolderID = folder.ParentID; | 371 | invService.MoveFolder(folder); |
372 | // folder.ParentID = destinationFolderID; | 372 | } |
373 | // invService.MoveFolder(folder); | 373 | } |
374 | // } | 374 | |
375 | // } | 375 | // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). |
376 | // | 376 | if (previousParentFolderID != null) |
377 | // // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). | 377 | { |
378 | // if (previousParentFolderID != null) | 378 | InventoryFolderBase previousParentFolder |
379 | // { | 379 | = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); |
380 | // InventoryFolderBase previousParentFolder | 380 | previousParentFolder = invService.GetFolder(previousParentFolder); |
381 | // = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); | 381 | scene.SendInventoryUpdate(client, previousParentFolder, true, true); |
382 | // previousParentFolder = invService.GetFolder(previousParentFolder); | 382 | |
383 | // scene.SendInventoryUpdate(client, previousParentFolder, true, true); | 383 | scene.SendInventoryUpdate(client, destinationFolder, true, true); |
384 | // | 384 | } |
385 | // scene.SendInventoryUpdate(client, destinationFolder, true, true); | 385 | } |
386 | // } | 386 | } |
387 | // } | ||
388 | // } | ||
389 | else if ( | 387 | else if ( |
390 | im.dialog == (byte)InstantMessageDialog.InventoryDeclined | 388 | im.dialog == (byte)InstantMessageDialog.InventoryDeclined |
391 | || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) | 389 | || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) |
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index 232a4fe..a34f2d2 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs | |||
@@ -65,7 +65,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
65 | { | 65 | { |
66 | m_Enabled = true; | 66 | m_Enabled = true; |
67 | 67 | ||
68 | m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty); | 68 | m_ThisGridURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI", |
69 | new string[] { "Startup", "Hypergrid", "Messaging" }, String.Empty); | ||
70 | // Legacy. Remove soon! | ||
71 | m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL); | ||
69 | m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); | 72 | m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); |
70 | } | 73 | } |
71 | } | 74 | } |
@@ -151,7 +154,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
151 | 154 | ||
152 | void OnIncomingInstantMessage(GridInstantMessage im) | 155 | void OnIncomingInstantMessage(GridInstantMessage im) |
153 | { | 156 | { |
154 | if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) | 157 | if (im.dialog == (byte)InstantMessageDialog.RequestTeleport |
158 | || im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport) | ||
155 | { | 159 | { |
156 | UUID sessionID = new UUID(im.imSessionID); | 160 | UUID sessionID = new UUID(im.imSessionID); |
157 | 161 | ||
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index f3adb95..0c64f19 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs | |||
@@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
165 | (uint)presence.AbsolutePosition.Y, | 165 | (uint)presence.AbsolutePosition.Y, |
166 | (uint)presence.AbsolutePosition.Z + 2); | 166 | (uint)presence.AbsolutePosition.Z + 2); |
167 | 167 | ||
168 | m_log.DebugFormat("[LURE]: TP invite with message {0}", message); | 168 | m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType); |
169 | 169 | ||
170 | GridInstantMessage m; | 170 | GridInstantMessage m; |
171 | 171 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs index 7f30e5a..2eb9bfb 100644 --- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs | |||
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Framework | |||
55 | /// <summary> | 55 | /// <summary> |
56 | /// Each agent has its own capabilities handler. | 56 | /// Each agent has its own capabilities handler. |
57 | /// </summary> | 57 | /// </summary> |
58 | protected Dictionary<UUID, Caps> m_capsObjects = new Dictionary<UUID, Caps>(); | 58 | protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>(); |
59 | 59 | ||
60 | protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); | 60 | protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); |
61 | protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds | 61 | protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds |
@@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Framework | |||
100 | get { return null; } | 100 | get { return null; } |
101 | } | 101 | } |
102 | 102 | ||
103 | public void CreateCaps(UUID agentId) | 103 | public void CreateCaps(UUID agentId, uint circuitCode) |
104 | { | 104 | { |
105 | int flags = m_scene.GetUserFlags(agentId); | 105 | int flags = m_scene.GetUserFlags(agentId); |
106 | if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) | 106 | if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) |
@@ -108,9 +108,9 @@ namespace OpenSim.Region.CoreModules.Framework | |||
108 | 108 | ||
109 | String capsObjectPath = GetCapsPath(agentId); | 109 | String capsObjectPath = GetCapsPath(agentId); |
110 | 110 | ||
111 | if (m_capsObjects.ContainsKey(agentId)) | 111 | if (m_capsObjects.ContainsKey(circuitCode)) |
112 | { | 112 | { |
113 | Caps oldCaps = m_capsObjects[agentId]; | 113 | Caps oldCaps = m_capsObjects[circuitCode]; |
114 | 114 | ||
115 | m_log.DebugFormat( | 115 | m_log.DebugFormat( |
116 | "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", | 116 | "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", |
@@ -125,12 +125,12 @@ namespace OpenSim.Region.CoreModules.Framework | |||
125 | (MainServer.Instance == null) ? 0: MainServer.Instance.Port, | 125 | (MainServer.Instance == null) ? 0: MainServer.Instance.Port, |
126 | capsObjectPath, agentId, m_scene.RegionInfo.RegionName); | 126 | capsObjectPath, agentId, m_scene.RegionInfo.RegionName); |
127 | 127 | ||
128 | m_capsObjects[agentId] = caps; | 128 | m_capsObjects[circuitCode] = caps; |
129 | 129 | ||
130 | m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); | 130 | m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); |
131 | } | 131 | } |
132 | 132 | ||
133 | public void RemoveCaps(UUID agentId) | 133 | public void RemoveCaps(UUID agentId, uint circuitCode) |
134 | { | 134 | { |
135 | if (childrenSeeds.ContainsKey(agentId)) | 135 | if (childrenSeeds.ContainsKey(agentId)) |
136 | { | 136 | { |
@@ -139,11 +139,11 @@ namespace OpenSim.Region.CoreModules.Framework | |||
139 | 139 | ||
140 | lock (m_capsObjects) | 140 | lock (m_capsObjects) |
141 | { | 141 | { |
142 | if (m_capsObjects.ContainsKey(agentId)) | 142 | if (m_capsObjects.ContainsKey(circuitCode)) |
143 | { | 143 | { |
144 | m_capsObjects[agentId].DeregisterHandlers(); | 144 | m_capsObjects[circuitCode].DeregisterHandlers(); |
145 | m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); | 145 | m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[circuitCode]); |
146 | m_capsObjects.Remove(agentId); | 146 | m_capsObjects.Remove(circuitCode); |
147 | } | 147 | } |
148 | else | 148 | else |
149 | { | 149 | { |
@@ -154,19 +154,30 @@ namespace OpenSim.Region.CoreModules.Framework | |||
154 | } | 154 | } |
155 | } | 155 | } |
156 | 156 | ||
157 | public Caps GetCapsForUser(UUID agentId) | 157 | public Caps GetCapsForUser(uint circuitCode) |
158 | { | 158 | { |
159 | lock (m_capsObjects) | 159 | lock (m_capsObjects) |
160 | { | 160 | { |
161 | if (m_capsObjects.ContainsKey(agentId)) | 161 | if (m_capsObjects.ContainsKey(circuitCode)) |
162 | { | 162 | { |
163 | return m_capsObjects[agentId]; | 163 | return m_capsObjects[circuitCode]; |
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
167 | return null; | 167 | return null; |
168 | } | 168 | } |
169 | 169 | ||
170 | public void ActivateCaps(uint circuitCode) | ||
171 | { | ||
172 | lock (m_capsObjects) | ||
173 | { | ||
174 | if (m_capsObjects.ContainsKey(circuitCode)) | ||
175 | { | ||
176 | m_capsObjects[circuitCode].Activate(); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
170 | public void SetAgentCapsSeeds(AgentCircuitData agent) | 181 | public void SetAgentCapsSeeds(AgentCircuitData agent) |
171 | { | 182 | { |
172 | capsPaths[agent.AgentID] = agent.CapsPath; | 183 | capsPaths[agent.AgentID] = agent.CapsPath; |
@@ -237,9 +248,9 @@ namespace OpenSim.Region.CoreModules.Framework | |||
237 | StringBuilder caps = new StringBuilder(); | 248 | StringBuilder caps = new StringBuilder(); |
238 | caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); | 249 | caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); |
239 | 250 | ||
240 | foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) | 251 | foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) |
241 | { | 252 | { |
242 | caps.AppendFormat("** User {0}:\n", kvp.Key); | 253 | caps.AppendFormat("** Circuit {0}:\n", kvp.Key); |
243 | 254 | ||
244 | for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); ) | 255 | for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); ) |
245 | { | 256 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs new file mode 100644 index 0000000..1f1568f --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs | |||
@@ -0,0 +1,119 @@ | |||
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 log4net; | ||
32 | using Mono.Addins; | ||
33 | using Nini.Config; | ||
34 | using OpenMetaverse; | ||
35 | using OpenMetaverse.Packets; | ||
36 | using OpenMetaverse.StructuredData; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Region.Framework; | ||
39 | using OpenSim.Region.Framework.Interfaces; | ||
40 | using OpenSim.Region.Framework.Scenes; | ||
41 | |||
42 | namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule | ||
43 | { | ||
44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] | ||
45 | public class DAExampleModule : INonSharedRegionModule | ||
46 | { | ||
47 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
48 | |||
49 | private static readonly bool ENABLED = false; // enable for testing | ||
50 | |||
51 | public const string DANamespace = "DAExample Module"; | ||
52 | |||
53 | protected Scene m_scene; | ||
54 | protected IDialogModule m_dialogMod; | ||
55 | |||
56 | public string Name { get { return "DAExample Module"; } } | ||
57 | public Type ReplaceableInterface { get { return null; } } | ||
58 | |||
59 | public void Initialise(IConfigSource source) {} | ||
60 | |||
61 | public void AddRegion(Scene scene) | ||
62 | { | ||
63 | if (ENABLED) | ||
64 | { | ||
65 | m_scene = scene; | ||
66 | m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; | ||
67 | m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | public void RemoveRegion(Scene scene) | ||
72 | { | ||
73 | if (ENABLED) | ||
74 | { | ||
75 | m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | public void RegionLoaded(Scene scene) {} | ||
80 | |||
81 | public void Close() | ||
82 | { | ||
83 | RemoveRegion(m_scene); | ||
84 | } | ||
85 | |||
86 | protected bool OnSceneGroupMove(UUID groupId, Vector3 delta) | ||
87 | { | ||
88 | OSDMap attrs = null; | ||
89 | SceneObjectPart sop = m_scene.GetSceneObjectPart(groupId); | ||
90 | |||
91 | if (sop == null) | ||
92 | return true; | ||
93 | |||
94 | if (!sop.DynAttrs.TryGetValue(DANamespace, out attrs)) | ||
95 | attrs = new OSDMap(); | ||
96 | |||
97 | OSDInteger newValue; | ||
98 | |||
99 | // We have to lock on the entire dynamic attributes map to avoid race conditions with serialization code. | ||
100 | lock (sop.DynAttrs) | ||
101 | { | ||
102 | if (!attrs.ContainsKey("moves")) | ||
103 | newValue = new OSDInteger(1); | ||
104 | else | ||
105 | newValue = new OSDInteger(attrs["moves"].AsInteger() + 1); | ||
106 | |||
107 | attrs["moves"] = newValue; | ||
108 | |||
109 | sop.DynAttrs[DANamespace] = attrs; | ||
110 | } | ||
111 | |||
112 | sop.ParentGroup.HasGroupChanged = true; | ||
113 | |||
114 | m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue)); | ||
115 | |||
116 | return true; | ||
117 | } | ||
118 | } | ||
119 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs new file mode 100644 index 0000000..650aa35 --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs | |||
@@ -0,0 +1,139 @@ | |||
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 log4net; | ||
32 | using Mono.Addins; | ||
33 | using Nini.Config; | ||
34 | using OpenMetaverse; | ||
35 | using OpenMetaverse.Packets; | ||
36 | using OpenMetaverse.StructuredData; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Region.Framework; | ||
39 | using OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule; | ||
40 | using OpenSim.Region.Framework.Interfaces; | ||
41 | using OpenSim.Region.Framework.Scenes; | ||
42 | |||
43 | namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule | ||
44 | { | ||
45 | /// <summary> | ||
46 | /// Example module for experimenting with and demonstrating dynamic object ideas. | ||
47 | /// </summary> | ||
48 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DOExampleModule")] | ||
49 | public class DOExampleModule : INonSharedRegionModule | ||
50 | { | ||
51 | public class MyObject | ||
52 | { | ||
53 | public int Moves { get; set; } | ||
54 | |||
55 | public MyObject(int moves) | ||
56 | { | ||
57 | Moves = moves; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
62 | |||
63 | private static readonly bool ENABLED = false; // enable for testing | ||
64 | |||
65 | private Scene m_scene; | ||
66 | private IDialogModule m_dialogMod; | ||
67 | |||
68 | public string Name { get { return "DOExample Module"; } } | ||
69 | public Type ReplaceableInterface { get { return null; } } | ||
70 | |||
71 | public void Initialise(IConfigSource source) {} | ||
72 | |||
73 | public void AddRegion(Scene scene) | ||
74 | { | ||
75 | if (ENABLED) | ||
76 | { | ||
77 | m_scene = scene; | ||
78 | m_scene.EventManager.OnObjectAddedToScene += OnObjectAddedToScene; | ||
79 | m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; | ||
80 | m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | public void RemoveRegion(Scene scene) | ||
85 | { | ||
86 | if (ENABLED) | ||
87 | { | ||
88 | m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | public void RegionLoaded(Scene scene) {} | ||
93 | |||
94 | public void Close() | ||
95 | { | ||
96 | RemoveRegion(m_scene); | ||
97 | } | ||
98 | |||
99 | private void OnObjectAddedToScene(SceneObjectGroup so) | ||
100 | { | ||
101 | SceneObjectPart rootPart = so.RootPart; | ||
102 | |||
103 | OSDMap attrs; | ||
104 | |||
105 | int movesSoFar = 0; | ||
106 | |||
107 | // Console.WriteLine("Here for {0}", so.Name); | ||
108 | |||
109 | if (rootPart.DynAttrs.TryGetValue(DAExampleModule.DANamespace, out attrs)) | ||
110 | { | ||
111 | movesSoFar = attrs["moves"].AsInteger(); | ||
112 | |||
113 | m_log.DebugFormat( | ||
114 | "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name); | ||
115 | } | ||
116 | |||
117 | rootPart.DynObjs.Add(Name, new MyObject(movesSoFar)); | ||
118 | } | ||
119 | |||
120 | private bool OnSceneGroupMove(UUID groupId, Vector3 delta) | ||
121 | { | ||
122 | SceneObjectGroup so = m_scene.GetSceneObjectGroup(groupId); | ||
123 | |||
124 | if (so == null) | ||
125 | return true; | ||
126 | |||
127 | object rawObj = so.RootPart.DynObjs.Get(Name); | ||
128 | |||
129 | if (rawObj != null) | ||
130 | { | ||
131 | MyObject myObj = (MyObject)rawObj; | ||
132 | |||
133 | m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", so.Name, so.UUID, ++myObj.Moves)); | ||
134 | } | ||
135 | |||
136 | return true; | ||
137 | } | ||
138 | } | ||
139 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index cb09047..b70aeb7 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -33,6 +33,7 @@ using System.Threading; | |||
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Framework.Capabilities; | 34 | using OpenSim.Framework.Capabilities; |
35 | using OpenSim.Framework.Client; | 35 | using OpenSim.Framework.Client; |
36 | using OpenSim.Framework.Monitoring; | ||
36 | using OpenSim.Region.Framework.Interfaces; | 37 | using OpenSim.Region.Framework.Interfaces; |
37 | using OpenSim.Region.Framework.Scenes; | 38 | using OpenSim.Region.Framework.Scenes; |
38 | using OpenSim.Region.Physics.Manager; | 39 | using OpenSim.Region.Physics.Manager; |
@@ -66,6 +67,42 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
66 | /// </summary> | 67 | /// </summary> |
67 | public bool WaitForAgentArrivedAtDestination { get; set; } | 68 | public bool WaitForAgentArrivedAtDestination { get; set; } |
68 | 69 | ||
70 | /// <summary> | ||
71 | /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests. | ||
72 | /// </summary> | ||
73 | /// <remarks> | ||
74 | /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a | ||
75 | /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the | ||
76 | /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport | ||
77 | /// cancellation consistently suceed. | ||
78 | /// </remarks> | ||
79 | public bool DisableInterRegionTeleportCancellation { get; set; } | ||
80 | |||
81 | /// <summary> | ||
82 | /// Number of times inter-region teleport was attempted. | ||
83 | /// </summary> | ||
84 | private Stat m_interRegionTeleportAttempts; | ||
85 | |||
86 | /// <summary> | ||
87 | /// Number of times inter-region teleport was aborted (due to simultaneous client logout). | ||
88 | /// </summary> | ||
89 | private Stat m_interRegionTeleportAborts; | ||
90 | |||
91 | /// <summary> | ||
92 | /// Number of times inter-region teleport was successfully cancelled by the client. | ||
93 | /// </summary> | ||
94 | private Stat m_interRegionTeleportCancels; | ||
95 | |||
96 | /// <summary> | ||
97 | /// Number of times inter-region teleport failed due to server/client/network problems (e.g. viewer failed to | ||
98 | /// connect with destination region). | ||
99 | /// </summary> | ||
100 | /// <remarks> | ||
101 | /// This is not necessarily a problem for this simulator - in open-grid/hg conditions, viewer connectivity to | ||
102 | /// destination simulator is unknown. | ||
103 | /// </remarks> | ||
104 | private Stat m_interRegionTeleportFailures; | ||
105 | |||
69 | protected bool m_Enabled = false; | 106 | protected bool m_Enabled = false; |
70 | 107 | ||
71 | public Scene Scene { get; private set; } | 108 | public Scene Scene { get; private set; } |
@@ -80,6 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
80 | new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); | 117 | new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); |
81 | 118 | ||
82 | private IEventQueue m_eqModule; | 119 | private IEventQueue m_eqModule; |
120 | private IRegionCombinerModule m_regionCombinerModule; | ||
83 | 121 | ||
84 | #region ISharedRegionModule | 122 | #region ISharedRegionModule |
85 | 123 | ||
@@ -116,6 +154,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
116 | IConfig transferConfig = source.Configs["EntityTransfer"]; | 154 | IConfig transferConfig = source.Configs["EntityTransfer"]; |
117 | if (transferConfig != null) | 155 | if (transferConfig != null) |
118 | { | 156 | { |
157 | DisableInterRegionTeleportCancellation | ||
158 | = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); | ||
159 | |||
119 | WaitForAgentArrivedAtDestination | 160 | WaitForAgentArrivedAtDestination |
120 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); | 161 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); |
121 | 162 | ||
@@ -142,6 +183,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
142 | 183 | ||
143 | Scene = scene; | 184 | Scene = scene; |
144 | 185 | ||
186 | m_interRegionTeleportAttempts = | ||
187 | new Stat( | ||
188 | "InterRegionTeleportAttempts", | ||
189 | "Number of inter-region teleports attempted.", | ||
190 | "This does not count attempts which failed due to pre-conditions (e.g. target simulator refused access).\n" | ||
191 | + "You can get successfully teleports by subtracting aborts, cancels and teleport failures from this figure.", | ||
192 | "", | ||
193 | "entitytransfer", | ||
194 | Scene.Name, | ||
195 | StatType.Push, | ||
196 | null, | ||
197 | StatVerbosity.Debug); | ||
198 | |||
199 | m_interRegionTeleportAborts = | ||
200 | new Stat( | ||
201 | "InterRegionTeleportAborts", | ||
202 | "Number of inter-region teleports aborted due to client actions.", | ||
203 | "The chief action is simultaneous logout whilst teleporting.", | ||
204 | "", | ||
205 | "entitytransfer", | ||
206 | Scene.Name, | ||
207 | StatType.Push, | ||
208 | null, | ||
209 | StatVerbosity.Debug); | ||
210 | |||
211 | m_interRegionTeleportCancels = | ||
212 | new Stat( | ||
213 | "InterRegionTeleportCancels", | ||
214 | "Number of inter-region teleports cancelled by the client.", | ||
215 | null, | ||
216 | "", | ||
217 | "entitytransfer", | ||
218 | Scene.Name, | ||
219 | StatType.Push, | ||
220 | null, | ||
221 | StatVerbosity.Debug); | ||
222 | |||
223 | m_interRegionTeleportFailures = | ||
224 | new Stat( | ||
225 | "InterRegionTeleportFailures", | ||
226 | "Number of inter-region teleports that failed due to server/client/network issues.", | ||
227 | "This number may not be very helpful in open-grid/hg situations as the network connectivity/quality of destinations is uncontrollable.", | ||
228 | "", | ||
229 | "entitytransfer", | ||
230 | Scene.Name, | ||
231 | StatType.Push, | ||
232 | null, | ||
233 | StatVerbosity.Debug); | ||
234 | |||
235 | StatsManager.RegisterStat(m_interRegionTeleportAttempts); | ||
236 | StatsManager.RegisterStat(m_interRegionTeleportAborts); | ||
237 | StatsManager.RegisterStat(m_interRegionTeleportCancels); | ||
238 | StatsManager.RegisterStat(m_interRegionTeleportFailures); | ||
239 | |||
145 | scene.RegisterModuleInterface<IEntityTransferModule>(this); | 240 | scene.RegisterModuleInterface<IEntityTransferModule>(this); |
146 | scene.EventManager.OnNewClient += OnNewClient; | 241 | scene.EventManager.OnNewClient += OnNewClient; |
147 | } | 242 | } |
@@ -150,12 +245,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
150 | { | 245 | { |
151 | client.OnTeleportHomeRequest += TriggerTeleportHome; | 246 | client.OnTeleportHomeRequest += TriggerTeleportHome; |
152 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; | 247 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; |
153 | client.OnTeleportCancel += TeleportCancel; | 248 | |
249 | if (!DisableInterRegionTeleportCancellation) | ||
250 | client.OnTeleportCancel += OnClientCancelTeleport; | ||
251 | |||
252 | client.OnConnectionClosed += OnConnectionClosed; | ||
154 | } | 253 | } |
155 | 254 | ||
156 | public virtual void Close() {} | 255 | public virtual void Close() {} |
157 | 256 | ||
158 | public virtual void RemoveRegion(Scene scene) {} | 257 | public virtual void RemoveRegion(Scene scene) |
258 | { | ||
259 | if (m_Enabled) | ||
260 | { | ||
261 | StatsManager.DeregisterStat(m_interRegionTeleportAttempts); | ||
262 | StatsManager.DeregisterStat(m_interRegionTeleportAborts); | ||
263 | StatsManager.DeregisterStat(m_interRegionTeleportCancels); | ||
264 | StatsManager.DeregisterStat(m_interRegionTeleportFailures); | ||
265 | } | ||
266 | } | ||
159 | 267 | ||
160 | public virtual void RegionLoaded(Scene scene) | 268 | public virtual void RegionLoaded(Scene scene) |
161 | { | 269 | { |
@@ -163,12 +271,33 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
163 | return; | 271 | return; |
164 | 272 | ||
165 | m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); | 273 | m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); |
274 | m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>(); | ||
166 | } | 275 | } |
167 | 276 | ||
168 | #endregion | 277 | #endregion |
169 | 278 | ||
170 | #region Agent Teleports | 279 | #region Agent Teleports |
171 | 280 | ||
281 | private void OnConnectionClosed(IClientAPI client) | ||
282 | { | ||
283 | if (client.IsLoggingOut) | ||
284 | { | ||
285 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting); | ||
286 | |||
287 | m_log.DebugFormat( | ||
288 | "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", | ||
289 | client.Name, Scene.Name); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | private void OnClientCancelTeleport(IClientAPI client) | ||
294 | { | ||
295 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling); | ||
296 | |||
297 | m_log.DebugFormat( | ||
298 | "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name); | ||
299 | } | ||
300 | |||
172 | public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) | 301 | public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) |
173 | { | 302 | { |
174 | if (sp.Scene.Permissions.IsGridGod(sp.UUID)) | 303 | if (sp.Scene.Permissions.IsGridGod(sp.UUID)) |
@@ -180,13 +309,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
180 | if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) | 309 | if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) |
181 | return; | 310 | return; |
182 | 311 | ||
183 | // Reset animations; the viewer does that in teleports. | ||
184 | sp.Animator.ResetAnimations(); | ||
185 | |||
186 | string destinationRegionName = "(not found)"; | 312 | string destinationRegionName = "(not found)"; |
187 | 313 | ||
314 | // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection | ||
315 | // of whether the destination region completes the teleport. | ||
316 | if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) | ||
317 | { | ||
318 | m_log.DebugFormat( | ||
319 | "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.", | ||
320 | sp.Name, sp.UUID, position, regionHandle); | ||
321 | |||
322 | return; | ||
323 | } | ||
324 | |||
188 | try | 325 | try |
189 | { | 326 | { |
327 | // Reset animations; the viewer does that in teleports. | ||
328 | sp.Animator.ResetAnimations(); | ||
329 | |||
190 | if (regionHandle == sp.Scene.RegionInfo.RegionHandle) | 330 | if (regionHandle == sp.Scene.RegionInfo.RegionHandle) |
191 | { | 331 | { |
192 | destinationRegionName = sp.Scene.RegionInfo.RegionName; | 332 | destinationRegionName = sp.Scene.RegionInfo.RegionName; |
@@ -195,12 +335,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
195 | } | 335 | } |
196 | else // Another region possibly in another simulator | 336 | else // Another region possibly in another simulator |
197 | { | 337 | { |
198 | GridRegion finalDestination; | 338 | GridRegion finalDestination = null; |
199 | TeleportAgentToDifferentRegion( | 339 | try |
200 | sp, regionHandle, position, lookAt, teleportFlags, out finalDestination); | 340 | { |
201 | 341 | TeleportAgentToDifferentRegion( | |
202 | if (finalDestination != null) | 342 | sp, regionHandle, position, lookAt, teleportFlags, out finalDestination); |
203 | destinationRegionName = finalDestination.RegionName; | 343 | } |
344 | finally | ||
345 | { | ||
346 | if (finalDestination != null) | ||
347 | destinationRegionName = finalDestination.RegionName; | ||
348 | } | ||
204 | } | 349 | } |
205 | } | 350 | } |
206 | catch (Exception e) | 351 | catch (Exception e) |
@@ -210,11 +355,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
210 | sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, | 355 | sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, |
211 | e.Message, e.StackTrace); | 356 | e.Message, e.StackTrace); |
212 | 357 | ||
213 | // Make sure that we clear the in-transit flag so that future teleport attempts don't always fail. | ||
214 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
215 | |||
216 | sp.ControllingClient.SendTeleportFailed("Internal error"); | 358 | sp.ControllingClient.SendTeleportFailed("Internal error"); |
217 | } | 359 | } |
360 | finally | ||
361 | { | ||
362 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
363 | } | ||
218 | } | 364 | } |
219 | 365 | ||
220 | /// <summary> | 366 | /// <summary> |
@@ -230,23 +376,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
230 | "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}", | 376 | "[ENTITY TRANSFER MODULE]: Teleport for {0} to {1} within {2}", |
231 | sp.Name, position, sp.Scene.RegionInfo.RegionName); | 377 | sp.Name, position, sp.Scene.RegionInfo.RegionName); |
232 | 378 | ||
233 | if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) | ||
234 | { | ||
235 | m_log.DebugFormat( | ||
236 | "[ENTITY TRANSFER MODULE]: Ignoring within region teleport request of {0} {1} to {2} - agent is already in transit.", | ||
237 | sp.Name, sp.UUID, position); | ||
238 | |||
239 | return; | ||
240 | } | ||
241 | |||
242 | // Teleport within the same region | 379 | // Teleport within the same region |
243 | if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) | 380 | if (IsOutsideRegion(sp.Scene, position) || position.Z < 0) |
244 | { | 381 | { |
245 | Vector3 emergencyPos = new Vector3(128, 128, 128); | 382 | Vector3 emergencyPos = new Vector3(128, 128, 128); |
246 | 383 | ||
247 | m_log.WarnFormat( | 384 | m_log.WarnFormat( |
248 | "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", | 385 | "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}. Substituting {4}", |
249 | position, sp.Name, sp.UUID, emergencyPos); | 386 | position, sp.Name, sp.UUID, Scene.Name, emergencyPos); |
250 | 387 | ||
251 | position = emergencyPos; | 388 | position = emergencyPos; |
252 | } | 389 | } |
@@ -287,7 +424,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
287 | } | 424 | } |
288 | 425 | ||
289 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 426 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
290 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
291 | } | 427 | } |
292 | 428 | ||
293 | /// <summary> | 429 | /// <summary> |
@@ -341,7 +477,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
341 | // | 477 | // |
342 | // This is it | 478 | // This is it |
343 | // | 479 | // |
344 | DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags); | 480 | DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags); |
345 | // | 481 | // |
346 | // | 482 | // |
347 | // | 483 | // |
@@ -396,27 +532,54 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
396 | && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; | 532 | && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; |
397 | } | 533 | } |
398 | 534 | ||
535 | /// <summary> | ||
536 | /// Wraps DoTeleportInternal() and manages the transfer state. | ||
537 | /// </summary> | ||
399 | public void DoTeleport( | 538 | public void DoTeleport( |
400 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, | 539 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, |
401 | Vector3 position, Vector3 lookAt, uint teleportFlags) | 540 | Vector3 position, Vector3 lookAt, uint teleportFlags) |
402 | { | 541 | { |
403 | // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection | 542 | // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection |
404 | // of whether the destination region completes the teleport. | 543 | // of whether the destination region completes the teleport. |
405 | m_entityTransferStateMachine.SetInTransit(sp.UUID); | 544 | if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) |
406 | // if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) | 545 | { |
407 | // { | 546 | m_log.DebugFormat( |
408 | // m_log.DebugFormat( | 547 | "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", |
409 | // "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", | 548 | sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); |
410 | // sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); | ||
411 | // | ||
412 | // return; | ||
413 | // } | ||
414 | 549 | ||
415 | if (reg == null || finalDestination == null) | 550 | return; |
551 | } | ||
552 | |||
553 | try | ||
554 | { | ||
555 | DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags); | ||
556 | } | ||
557 | catch (Exception e) | ||
558 | { | ||
559 | m_log.ErrorFormat( | ||
560 | "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}", | ||
561 | sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, finalDestination.RegionName, | ||
562 | e.Message, e.StackTrace); | ||
563 | |||
564 | sp.ControllingClient.SendTeleportFailed("Internal error"); | ||
565 | } | ||
566 | finally | ||
416 | { | 567 | { |
417 | sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); | ||
418 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | 568 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); |
569 | } | ||
570 | } | ||
419 | 571 | ||
572 | /// <summary> | ||
573 | /// Teleports the agent to another region. | ||
574 | /// This method doesn't manage the transfer state; the caller must do that. | ||
575 | /// </summary> | ||
576 | private void DoTeleportInternal( | ||
577 | ScenePresence sp, GridRegion reg, GridRegion finalDestination, | ||
578 | Vector3 position, Vector3 lookAt, uint teleportFlags) | ||
579 | { | ||
580 | if (reg == null || finalDestination == null) | ||
581 | { | ||
582 | sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); | ||
420 | return; | 583 | return; |
421 | } | 584 | } |
422 | 585 | ||
@@ -436,8 +599,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
436 | sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, | 599 | sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, |
437 | MaxTransferDistance)); | 600 | MaxTransferDistance)); |
438 | 601 | ||
439 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
440 | |||
441 | return; | 602 | return; |
442 | } | 603 | } |
443 | 604 | ||
@@ -455,7 +616,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
455 | if (endPoint == null || endPoint.Address == null) | 616 | if (endPoint == null || endPoint.Address == null) |
456 | { | 617 | { |
457 | sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); | 618 | sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); |
458 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
459 | 619 | ||
460 | return; | 620 | return; |
461 | } | 621 | } |
@@ -465,19 +625,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
465 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", | 625 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", |
466 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); | 626 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); |
467 | 627 | ||
468 | // if (!sp.ValidateAttachments()) | ||
469 | // { | ||
470 | // sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); | ||
471 | // return; | ||
472 | // } | ||
473 | |||
474 | string reason; | 628 | string reason; |
475 | string version; | 629 | string version; |
476 | if (!Scene.SimulationService.QueryAccess( | 630 | if (!Scene.SimulationService.QueryAccess( |
477 | finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) | 631 | finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) |
478 | { | 632 | { |
479 | sp.ControllingClient.SendTeleportFailed(reason); | 633 | sp.ControllingClient.SendTeleportFailed(reason); |
480 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
481 | 634 | ||
482 | m_log.DebugFormat( | 635 | m_log.DebugFormat( |
483 | "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", | 636 | "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", |
@@ -486,6 +639,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
486 | return; | 639 | return; |
487 | } | 640 | } |
488 | 641 | ||
642 | // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target | ||
643 | // simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these | ||
644 | // as server attempts. | ||
645 | m_interRegionTeleportAttempts.Value++; | ||
646 | |||
489 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); | 647 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); |
490 | 648 | ||
491 | // Fixing a bug where teleporting while sitting results in the avatar ending up removed from | 649 | // Fixing a bug where teleporting while sitting results in the avatar ending up removed from |
@@ -495,6 +653,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
495 | else if (sp.Flying) | 653 | else if (sp.Flying) |
496 | teleportFlags |= (uint)TeleportFlags.IsFlying; | 654 | teleportFlags |= (uint)TeleportFlags.IsFlying; |
497 | 655 | ||
656 | if (DisableInterRegionTeleportCancellation) | ||
657 | teleportFlags |= (uint)TeleportFlags.DisableCancel; | ||
658 | |||
498 | // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to | 659 | // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to |
499 | // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). | 660 | // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). |
500 | sp.ControllingClient.SendTeleportStart(teleportFlags); | 661 | sp.ControllingClient.SendTeleportStart(teleportFlags); |
@@ -531,11 +692,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
531 | } | 692 | } |
532 | 693 | ||
533 | // Let's create an agent there if one doesn't exist yet. | 694 | // Let's create an agent there if one doesn't exist yet. |
695 | // NOTE: logout will always be false for a non-HG teleport. | ||
534 | bool logout = false; | 696 | bool logout = false; |
535 | if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) | 697 | if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) |
536 | { | 698 | { |
699 | m_interRegionTeleportFailures.Value++; | ||
700 | |||
537 | sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); | 701 | sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); |
538 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
539 | 702 | ||
540 | m_log.DebugFormat( | 703 | m_log.DebugFormat( |
541 | "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", | 704 | "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", |
@@ -544,6 +707,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
544 | return; | 707 | return; |
545 | } | 708 | } |
546 | 709 | ||
710 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) | ||
711 | { | ||
712 | m_interRegionTeleportCancels.Value++; | ||
713 | |||
714 | m_log.DebugFormat( | ||
715 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", | ||
716 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
717 | |||
718 | return; | ||
719 | } | ||
720 | else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
721 | { | ||
722 | m_interRegionTeleportAborts.Value++; | ||
723 | |||
724 | m_log.DebugFormat( | ||
725 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", | ||
726 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
727 | |||
728 | return; | ||
729 | } | ||
730 | |||
547 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. | 731 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. |
548 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | 732 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); |
549 | 733 | ||
@@ -553,6 +737,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
553 | IClientIPEndpoint ipepClient; | 737 | IClientIPEndpoint ipepClient; |
554 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) | 738 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) |
555 | { | 739 | { |
740 | m_log.DebugFormat( | ||
741 | "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", | ||
742 | finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); | ||
743 | |||
556 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); | 744 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); |
557 | #region IP Translation for NAT | 745 | #region IP Translation for NAT |
558 | // Uses ipepClient above | 746 | // Uses ipepClient above |
@@ -565,11 +753,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
565 | 753 | ||
566 | if (m_eqModule != null) | 754 | if (m_eqModule != null) |
567 | { | 755 | { |
756 | // The EnableSimulator message makes the client establish a connection with the destination | ||
757 | // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the | ||
758 | // correct circuit code. | ||
568 | m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); | 759 | m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); |
569 | 760 | ||
570 | // ES makes the client send a UseCircuitCode message to the destination, | 761 | // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination |
571 | // which triggers a bunch of things there. | 762 | // simulator to confirm that it has established communication with the viewer. |
572 | // So let's wait | ||
573 | Thread.Sleep(200); | 763 | Thread.Sleep(200); |
574 | 764 | ||
575 | // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears | 765 | // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears |
@@ -580,6 +770,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
580 | } | 770 | } |
581 | else | 771 | else |
582 | { | 772 | { |
773 | // XXX: This is a little misleading since we're information the client of its avatar destination, | ||
774 | // which may or may not be a neighbour region of the source region. This path is probably little | ||
775 | // used anyway (with EQ being the one used). But it is currently being used for test code. | ||
583 | sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); | 776 | sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); |
584 | } | 777 | } |
585 | } | 778 | } |
@@ -597,23 +790,66 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
597 | 790 | ||
598 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); | 791 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); |
599 | 792 | ||
793 | // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to | ||
794 | // establish th econnection to the destination which makes it return true. | ||
795 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
796 | { | ||
797 | m_interRegionTeleportAborts.Value++; | ||
798 | |||
799 | m_log.DebugFormat( | ||
800 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", | ||
801 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
802 | |||
803 | return; | ||
804 | } | ||
805 | |||
806 | // A common teleport failure occurs when we can send CreateAgent to the | ||
807 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between | ||
808 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then | ||
809 | // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). | ||
600 | if (!UpdateAgent(reg, finalDestination, agent, sp)) | 810 | if (!UpdateAgent(reg, finalDestination, agent, sp)) |
601 | { | 811 | { |
602 | // Region doesn't take it | 812 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) |
813 | { | ||
814 | m_interRegionTeleportAborts.Value++; | ||
815 | |||
816 | m_log.DebugFormat( | ||
817 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", | ||
818 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
819 | |||
820 | return; | ||
821 | } | ||
822 | |||
603 | m_log.WarnFormat( | 823 | m_log.WarnFormat( |
604 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.", | 824 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", |
605 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 825 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
606 | 826 | ||
607 | Fail(sp, finalDestination, logout); | 827 | Fail(sp, finalDestination, logout, "Connection between viewer and destination region could not be established."); |
608 | return; | 828 | return; |
609 | } | 829 | } |
610 | 830 | ||
611 | sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "sending_dest"); | 831 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) |
832 | { | ||
833 | m_interRegionTeleportCancels.Value++; | ||
834 | |||
835 | m_log.DebugFormat( | ||
836 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", | ||
837 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
838 | |||
839 | CleanupFailedInterRegionTeleport(sp, finalDestination); | ||
840 | |||
841 | return; | ||
842 | } | ||
612 | 843 | ||
613 | m_log.DebugFormat( | 844 | m_log.DebugFormat( |
614 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", | 845 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", |
615 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); | 846 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); |
616 | 847 | ||
848 | // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, | ||
849 | // where that neighbour simulator could otherwise request a child agent create on the source which then | ||
850 | // closes our existing agent which is still signalled as root. | ||
851 | sp.IsChildAgent = true; | ||
852 | |||
617 | if (m_eqModule != null) | 853 | if (m_eqModule != null) |
618 | { | 854 | { |
619 | m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); | 855 | m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); |
@@ -624,19 +860,28 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
624 | teleportFlags, capsPath); | 860 | teleportFlags, capsPath); |
625 | } | 861 | } |
626 | 862 | ||
627 | // Let's set this to true tentatively. This does not trigger OnChildAgent | ||
628 | sp.IsChildAgent = true; | ||
629 | |||
630 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which | 863 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which |
631 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation | 864 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation |
632 | // that the client contacted the destination before we close things here. | 865 | // that the client contacted the destination before we close things here. |
633 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) | 866 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) |
634 | { | 867 | { |
868 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
869 | { | ||
870 | m_interRegionTeleportAborts.Value++; | ||
871 | |||
872 | m_log.DebugFormat( | ||
873 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", | ||
874 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
875 | |||
876 | return; | ||
877 | } | ||
878 | |||
635 | m_log.WarnFormat( | 879 | m_log.WarnFormat( |
636 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", | 880 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", |
637 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 881 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
638 | 882 | ||
639 | Fail(sp, finalDestination, logout); | 883 | Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion."); |
884 | |||
640 | return; | 885 | return; |
641 | } | 886 | } |
642 | 887 | ||
@@ -659,8 +904,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
659 | // Now let's make it officially a child agent | 904 | // Now let's make it officially a child agent |
660 | sp.MakeChildAgent(); | 905 | sp.MakeChildAgent(); |
661 | 906 | ||
662 | // sp.Scene.CleanDroppedAttachments(); | ||
663 | |||
664 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone | 907 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone |
665 | 908 | ||
666 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) | 909 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) |
@@ -680,27 +923,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
680 | // now we have a child agent in this region. | 923 | // now we have a child agent in this region. |
681 | sp.Reset(); | 924 | sp.Reset(); |
682 | } | 925 | } |
683 | |||
684 | // Commented pending deletion since this method no longer appears to do anything at all | ||
685 | // // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! | ||
686 | // if (sp.Scene.NeedSceneCacheClear(sp.UUID)) | ||
687 | // { | ||
688 | // m_log.DebugFormat( | ||
689 | // "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", | ||
690 | // sp.UUID); | ||
691 | // } | ||
692 | |||
693 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
694 | } | 926 | } |
695 | 927 | ||
696 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) | 928 | /// <summary> |
929 | /// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation. | ||
930 | /// </summary> | ||
931 | /// <remarks> | ||
932 | /// All operations here must be idempotent so that we can call this method at any point in the teleport process | ||
933 | /// up until we send the TeleportFinish event quene event to the viewer. | ||
934 | /// <remarks> | ||
935 | /// <param name='sp'> </param> | ||
936 | /// <param name='finalDestination'></param> | ||
937 | protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) | ||
697 | { | 938 | { |
698 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 939 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
699 | 940 | ||
700 | // Client never contacted destination. Let's restore everything back | ||
701 | sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); | ||
702 | |||
703 | // Fail. Reset it back | ||
704 | sp.IsChildAgent = false; | 941 | sp.IsChildAgent = false; |
705 | ReInstantiateScripts(sp); | 942 | ReInstantiateScripts(sp); |
706 | 943 | ||
@@ -708,10 +945,26 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
708 | 945 | ||
709 | // Finally, kill the agent we just created at the destination. | 946 | // Finally, kill the agent we just created at the destination. |
710 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); | 947 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); |
948 | } | ||
711 | 949 | ||
712 | sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); | 950 | /// <summary> |
951 | /// Signal that the inter-region teleport failed and perform cleanup. | ||
952 | /// </summary> | ||
953 | /// <param name='sp'></param> | ||
954 | /// <param name='finalDestination'></param> | ||
955 | /// <param name='logout'></param> | ||
956 | /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> | ||
957 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) | ||
958 | { | ||
959 | CleanupFailedInterRegionTeleport(sp, finalDestination); | ||
960 | |||
961 | m_interRegionTeleportFailures.Value++; | ||
713 | 962 | ||
714 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | 963 | sp.ControllingClient.SendTeleportFailed( |
964 | string.Format( | ||
965 | "Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason)); | ||
966 | |||
967 | sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); | ||
715 | } | 968 | } |
716 | 969 | ||
717 | protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) | 970 | protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) |
@@ -762,7 +1015,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
762 | 1015 | ||
763 | protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) | 1016 | protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) |
764 | { | 1017 | { |
765 | return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); | 1018 | if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) |
1019 | { | ||
1020 | Vector2 swCorner, neCorner; | ||
1021 | GetMegaregionViewRange(out swCorner, out neCorner); | ||
1022 | |||
1023 | m_log.DebugFormat( | ||
1024 | "[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}", | ||
1025 | Scene.Name, swCorner, neCorner, newRegionX, newRegionY); | ||
1026 | |||
1027 | return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y); | ||
1028 | } | ||
1029 | else | ||
1030 | { | ||
1031 | return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); | ||
1032 | } | ||
766 | } | 1033 | } |
767 | 1034 | ||
768 | protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) | 1035 | protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) |
@@ -866,6 +1133,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
866 | { | 1133 | { |
867 | version = String.Empty; | 1134 | version = String.Empty; |
868 | newpos = new Vector3(pos.X, pos.Y, pos.Z); | 1135 | newpos = new Vector3(pos.X, pos.Y, pos.Z); |
1136 | |||
1137 | // m_log.DebugFormat( | ||
1138 | // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); | ||
1139 | |||
869 | uint neighbourx = scene.RegionInfo.RegionLocX; | 1140 | uint neighbourx = scene.RegionInfo.RegionLocX; |
870 | uint neighboury = scene.RegionInfo.RegionLocY; | 1141 | uint neighboury = scene.RegionInfo.RegionLocY; |
871 | const float boundaryDistance = 1.7f; | 1142 | const float boundaryDistance = 1.7f; |
@@ -995,11 +1266,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
995 | return neighbourRegion; | 1266 | return neighbourRegion; |
996 | } | 1267 | } |
997 | 1268 | ||
998 | private void TeleportCancel(IClientAPI remoteClient) | ||
999 | { | ||
1000 | m_entityTransferStateMachine.ResetFromTransit(remoteClient.AgentId); | ||
1001 | } | ||
1002 | |||
1003 | public bool Cross(ScenePresence agent, bool isFlying) | 1269 | public bool Cross(ScenePresence agent, bool isFlying) |
1004 | { | 1270 | { |
1005 | uint x; | 1271 | uint x; |
@@ -1023,16 +1289,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1023 | } | 1289 | } |
1024 | 1290 | ||
1025 | 1291 | ||
1026 | public delegate void InformClientToInitateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, | 1292 | public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, |
1027 | Vector3 position, | 1293 | Vector3 position, |
1028 | Scene initiatingScene); | 1294 | Scene initiatingScene); |
1029 | 1295 | ||
1030 | private void InformClientToInitateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) | 1296 | private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) |
1031 | { | 1297 | { |
1032 | 1298 | ||
1033 | // This assumes that we know what our neighbours are. | 1299 | // This assumes that we know what our neighbours are. |
1034 | 1300 | ||
1035 | InformClientToInitateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync; | 1301 | InformClientToInitiateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync; |
1036 | d.BeginInvoke(agent, regionX, regionY, position, initiatingScene, | 1302 | d.BeginInvoke(agent, regionX, regionY, position, initiatingScene, |
1037 | InformClientToInitiateTeleportToLocationCompleted, | 1303 | InformClientToInitiateTeleportToLocationCompleted, |
1038 | d); | 1304 | d); |
@@ -1042,7 +1308,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1042 | Scene initiatingScene) | 1308 | Scene initiatingScene) |
1043 | { | 1309 | { |
1044 | Thread.Sleep(10000); | 1310 | Thread.Sleep(10000); |
1045 | 1311 | ||
1312 | m_log.DebugFormat( | ||
1313 | "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}", | ||
1314 | agent.Name, regionX, regionY, position, initiatingScene.Name); | ||
1315 | |||
1316 | agent.Scene.RequestTeleportLocation( | ||
1317 | agent.ControllingClient, | ||
1318 | Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize), | ||
1319 | position, | ||
1320 | agent.Lookat, | ||
1321 | (uint)Constants.TeleportFlags.ViaLocation); | ||
1322 | |||
1323 | /* | ||
1046 | IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); | 1324 | IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); |
1047 | if (im != null) | 1325 | if (im != null) |
1048 | { | 1326 | { |
@@ -1077,12 +1355,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1077 | }); | 1355 | }); |
1078 | 1356 | ||
1079 | } | 1357 | } |
1358 | */ | ||
1080 | } | 1359 | } |
1081 | 1360 | ||
1082 | private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar) | 1361 | private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar) |
1083 | { | 1362 | { |
1084 | InformClientToInitateTeleportToLocationDelegate icon = | 1363 | InformClientToInitiateTeleportToLocationDelegate icon = |
1085 | (InformClientToInitateTeleportToLocationDelegate)iar.AsyncState; | 1364 | (InformClientToInitiateTeleportToLocationDelegate)iar.AsyncState; |
1086 | icon.EndInvoke(iar); | 1365 | icon.EndInvoke(iar); |
1087 | } | 1366 | } |
1088 | 1367 | ||
@@ -1107,10 +1386,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1107 | bool isFlying, string version) | 1386 | bool isFlying, string version) |
1108 | { | 1387 | { |
1109 | if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) | 1388 | if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) |
1389 | { | ||
1390 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1110 | return agent; | 1391 | return agent; |
1392 | } | ||
1111 | 1393 | ||
1112 | if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) | 1394 | if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) |
1395 | { | ||
1396 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1113 | return agent; | 1397 | return agent; |
1398 | } | ||
1114 | 1399 | ||
1115 | CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); | 1400 | CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); |
1116 | return agent; | 1401 | return agent; |
@@ -1137,9 +1422,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1137 | // region doesn't take it | 1422 | // region doesn't take it |
1138 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); | 1423 | m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); |
1139 | 1424 | ||
1425 | m_log.WarnFormat( | ||
1426 | "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.", | ||
1427 | neighbourRegion.RegionName, agent.Name); | ||
1428 | |||
1140 | ReInstantiateScripts(agent); | 1429 | ReInstantiateScripts(agent); |
1141 | agent.AddToPhysicalScene(isFlying); | 1430 | agent.AddToPhysicalScene(isFlying); |
1142 | m_entityTransferStateMachine.ResetFromTransit(agent.UUID); | ||
1143 | 1431 | ||
1144 | return false; | 1432 | return false; |
1145 | } | 1433 | } |
@@ -1576,6 +1864,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1576 | } | 1864 | } |
1577 | 1865 | ||
1578 | /// <summary> | 1866 | /// <summary> |
1867 | /// Gets the range considered in view of this megaregion (assuming this is a megaregion). | ||
1868 | /// </summary> | ||
1869 | /// <remarks>Expressed in 256m units</remarks> | ||
1870 | /// <param name='swCorner'></param> | ||
1871 | /// <param name='neCorner'></param> | ||
1872 | private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner) | ||
1873 | { | ||
1874 | Border[] northBorders = Scene.NorthBorders.ToArray(); | ||
1875 | Border[] eastBorders = Scene.EastBorders.ToArray(); | ||
1876 | |||
1877 | Vector2 extent = Vector2.Zero; | ||
1878 | for (int i = 0; i < eastBorders.Length; i++) | ||
1879 | { | ||
1880 | extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X; | ||
1881 | } | ||
1882 | for (int i = 0; i < northBorders.Length; i++) | ||
1883 | { | ||
1884 | extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y; | ||
1885 | } | ||
1886 | |||
1887 | // Loss of fraction on purpose | ||
1888 | extent.X = ((int)extent.X / (int)Constants.RegionSize); | ||
1889 | extent.Y = ((int)extent.Y / (int)Constants.RegionSize); | ||
1890 | |||
1891 | swCorner.X = Scene.RegionInfo.RegionLocX - 1; | ||
1892 | swCorner.Y = Scene.RegionInfo.RegionLocY - 1; | ||
1893 | neCorner.X = Scene.RegionInfo.RegionLocX + extent.X; | ||
1894 | neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y; | ||
1895 | } | ||
1896 | |||
1897 | /// <summary> | ||
1579 | /// Return the list of regions that are considered to be neighbours to the given scene. | 1898 | /// Return the list of regions that are considered to be neighbours to the given scene. |
1580 | /// </summary> | 1899 | /// </summary> |
1581 | /// <param name="pScene"></param> | 1900 | /// <param name="pScene"></param> |
@@ -1587,15 +1906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1587 | Scene pScene = avatar.Scene; | 1906 | Scene pScene = avatar.Scene; |
1588 | RegionInfo m_regionInfo = pScene.RegionInfo; | 1907 | RegionInfo m_regionInfo = pScene.RegionInfo; |
1589 | 1908 | ||
1590 | Border[] northBorders = pScene.NorthBorders.ToArray(); | ||
1591 | Border[] southBorders = pScene.SouthBorders.ToArray(); | ||
1592 | Border[] eastBorders = pScene.EastBorders.ToArray(); | ||
1593 | Border[] westBorders = pScene.WestBorders.ToArray(); | ||
1594 | |||
1595 | // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't | 1909 | // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't |
1596 | // clear what should be done with a "far view" given that megaregions already extended the | 1910 | // clear what should be done with a "far view" given that megaregions already extended the |
1597 | // view to include everything in the megaregion | 1911 | // view to include everything in the megaregion |
1598 | if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1) | 1912 | if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) |
1599 | { | 1913 | { |
1600 | int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; | 1914 | int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; |
1601 | 1915 | ||
@@ -1613,27 +1927,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1613 | } | 1927 | } |
1614 | else | 1928 | else |
1615 | { | 1929 | { |
1616 | Vector2 extent = Vector2.Zero; | 1930 | Vector2 swCorner, neCorner; |
1617 | for (int i = 0; i < eastBorders.Length; i++) | 1931 | GetMegaregionViewRange(out swCorner, out neCorner); |
1618 | { | ||
1619 | extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X; | ||
1620 | } | ||
1621 | for (int i = 0; i < northBorders.Length; i++) | ||
1622 | { | ||
1623 | extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y; | ||
1624 | } | ||
1625 | |||
1626 | // Loss of fraction on purpose | ||
1627 | extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1; | ||
1628 | extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1; | ||
1629 | |||
1630 | int startX = (int)(pRegionLocX - 1) * (int)Constants.RegionSize; | ||
1631 | int startY = (int)(pRegionLocY - 1) * (int)Constants.RegionSize; | ||
1632 | 1932 | ||
1633 | int endX = ((int)pRegionLocX + (int)extent.X) * (int)Constants.RegionSize; | 1933 | List<GridRegion> neighbours |
1634 | int endY = ((int)pRegionLocY + (int)extent.Y) * (int)Constants.RegionSize; | 1934 | = pScene.GridService.GetRegionRange( |
1935 | m_regionInfo.ScopeID, | ||
1936 | (int)swCorner.X * (int)Constants.RegionSize, | ||
1937 | (int)neCorner.X * (int)Constants.RegionSize, | ||
1938 | (int)swCorner.Y * (int)Constants.RegionSize, | ||
1939 | (int)neCorner.Y * (int)Constants.RegionSize); | ||
1635 | 1940 | ||
1636 | List<GridRegion> neighbours = pScene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY); | ||
1637 | neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); | 1941 | neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); |
1638 | 1942 | ||
1639 | return neighbours; | 1943 | return neighbours; |
@@ -2054,7 +2358,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2054 | 2358 | ||
2055 | public bool IsInTransit(UUID id) | 2359 | public bool IsInTransit(UUID id) |
2056 | { | 2360 | { |
2057 | return m_entityTransferStateMachine.IsInTransit(id); | 2361 | return m_entityTransferStateMachine.GetAgentTransferState(id) != null; |
2058 | } | 2362 | } |
2059 | 2363 | ||
2060 | protected void ReInstantiateScripts(ScenePresence sp) | 2364 | protected void ReInstantiateScripts(ScenePresence sp) |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs index 70dd1bc..e903383 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs | |||
@@ -51,10 +51,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
51 | /// This is a state machine. | 51 | /// This is a state machine. |
52 | /// | 52 | /// |
53 | /// [Entry] => Preparing | 53 | /// [Entry] => Preparing |
54 | /// Preparing => { Transferring || CleaningUp || [Exit] } | 54 | /// Preparing => { Transferring || Cancelling || CleaningUp || Aborting || [Exit] } |
55 | /// Transferring => { ReceivedAtDestination || CleaningUp } | 55 | /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp || Aborting } |
56 | /// ReceivedAtDestination => CleaningUp | 56 | /// Cancelling => CleaningUp || Aborting |
57 | /// ReceivedAtDestination => CleaningUp || Aborting | ||
57 | /// CleaningUp => [Exit] | 58 | /// CleaningUp => [Exit] |
59 | /// Aborting => [Exit] | ||
58 | /// | 60 | /// |
59 | /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp | 61 | /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp |
60 | /// However, any state can transition to CleaningUp if the teleport has failed. | 62 | /// However, any state can transition to CleaningUp if the teleport has failed. |
@@ -64,7 +66,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
64 | Preparing, // The agent is being prepared for transfer | 66 | Preparing, // The agent is being prepared for transfer |
65 | Transferring, // The agent is in the process of being transferred to a destination | 67 | Transferring, // The agent is in the process of being transferred to a destination |
66 | ReceivedAtDestination, // The destination has notified us that the agent has been successfully received | 68 | ReceivedAtDestination, // The destination has notified us that the agent has been successfully received |
67 | CleaningUp // The agent is being changed to child/removed after a transfer | 69 | CleaningUp, // The agent is being changed to child/removed after a transfer |
70 | Cancelling, // The user has cancelled the teleport but we have yet to act upon this. | ||
71 | Aborting // The transfer is aborting. Unlike Cancelling, no compensating actions should be performed | ||
68 | } | 72 | } |
69 | 73 | ||
70 | /// <summary> | 74 | /// <summary> |
@@ -115,42 +119,114 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
115 | /// <param name='newState'></param> | 119 | /// <param name='newState'></param> |
116 | /// <returns></returns> | 120 | /// <returns></returns> |
117 | /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> | 121 | /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> |
118 | internal void UpdateInTransit(UUID id, AgentTransferState newState) | 122 | internal bool UpdateInTransit(UUID id, AgentTransferState newState) |
119 | { | 123 | { |
124 | bool transitionOkay = false; | ||
125 | |||
126 | // We don't want to throw an exception on cancel since this can come it at any time. | ||
127 | bool failIfNotOkay = true; | ||
128 | |||
129 | // Should be a failure message if failure is not okay. | ||
130 | string failureMessage = null; | ||
131 | |||
132 | AgentTransferState? oldState = null; | ||
133 | |||
120 | lock (m_agentsInTransit) | 134 | lock (m_agentsInTransit) |
121 | { | 135 | { |
122 | // Illegal to try and update an agent that's not actually in transit. | 136 | // Illegal to try and update an agent that's not actually in transit. |
123 | if (!m_agentsInTransit.ContainsKey(id)) | 137 | if (!m_agentsInTransit.ContainsKey(id)) |
124 | throw new Exception( | 138 | { |
125 | string.Format( | 139 | if (newState != AgentTransferState.Cancelling && newState != AgentTransferState.Aborting) |
126 | "Agent with ID {0} is not registered as in transit in {1}", | 140 | failureMessage = string.Format( |
127 | id, m_mod.Scene.RegionInfo.RegionName)); | 141 | "Agent with ID {0} is not registered as in transit in {1}", |
128 | 142 | id, m_mod.Scene.RegionInfo.RegionName); | |
129 | AgentTransferState oldState = m_agentsInTransit[id]; | 143 | else |
144 | failIfNotOkay = false; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | oldState = m_agentsInTransit[id]; | ||
130 | 149 | ||
131 | bool transitionOkay = false; | 150 | if (newState == AgentTransferState.Aborting) |
151 | { | ||
152 | transitionOkay = true; | ||
153 | } | ||
154 | else if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) | ||
155 | { | ||
156 | transitionOkay = true; | ||
157 | } | ||
158 | else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing) | ||
159 | { | ||
160 | transitionOkay = true; | ||
161 | } | ||
162 | else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring) | ||
163 | { | ||
164 | transitionOkay = true; | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | if (newState == AgentTransferState.Cancelling | ||
169 | && (oldState == AgentTransferState.Preparing || oldState == AgentTransferState.Transferring)) | ||
170 | { | ||
171 | transitionOkay = true; | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | failIfNotOkay = false; | ||
176 | } | ||
177 | } | ||
132 | 178 | ||
133 | if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) | 179 | if (!transitionOkay) |
134 | transitionOkay = true; | 180 | failureMessage |
135 | else if (newState == AgentTransferState.Transferring && oldState == AgentTransferState.Preparing) | 181 | = string.Format( |
136 | transitionOkay = true; | 182 | "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}", |
137 | else if (newState == AgentTransferState.ReceivedAtDestination && oldState == AgentTransferState.Transferring) | 183 | id, oldState, newState, m_mod.Scene.RegionInfo.RegionName); |
138 | transitionOkay = true; | 184 | } |
139 | 185 | ||
140 | if (transitionOkay) | 186 | if (transitionOkay) |
187 | { | ||
141 | m_agentsInTransit[id] = newState; | 188 | m_agentsInTransit[id] = newState; |
142 | else | 189 | |
143 | throw new Exception( | 190 | // m_log.DebugFormat( |
144 | string.Format( | 191 | // "[ENTITY TRANSFER STATE MACHINE]: Changed agent with id {0} from state {1} to {2} in {3}", |
145 | "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}", | 192 | // id, oldState, newState, m_mod.Scene.Name); |
146 | id, oldState, newState, m_mod.Scene.RegionInfo.RegionName)); | 193 | } |
194 | else if (failIfNotOkay) | ||
195 | { | ||
196 | throw new Exception(failureMessage); | ||
197 | } | ||
198 | // else | ||
199 | // { | ||
200 | // if (oldState != null) | ||
201 | // m_log.DebugFormat( | ||
202 | // "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} from state {1} to {2} in {3}", | ||
203 | // id, oldState, newState, m_mod.Scene.Name); | ||
204 | // else | ||
205 | // m_log.DebugFormat( | ||
206 | // "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} to state {1} in {2} since agent not in transit", | ||
207 | // id, newState, m_mod.Scene.Name); | ||
208 | // } | ||
147 | } | 209 | } |
210 | |||
211 | return transitionOkay; | ||
148 | } | 212 | } |
149 | 213 | ||
150 | internal bool IsInTransit(UUID id) | 214 | /// <summary> |
215 | /// Gets the current agent transfer state. | ||
216 | /// </summary> | ||
217 | /// <returns>Null if the agent is not in transit</returns> | ||
218 | /// <param name='id'> | ||
219 | /// Identifier. | ||
220 | /// </param> | ||
221 | internal AgentTransferState? GetAgentTransferState(UUID id) | ||
151 | { | 222 | { |
152 | lock (m_agentsInTransit) | 223 | lock (m_agentsInTransit) |
153 | return m_agentsInTransit.ContainsKey(id); | 224 | { |
225 | if (!m_agentsInTransit.ContainsKey(id)) | ||
226 | return null; | ||
227 | else | ||
228 | return m_agentsInTransit[id]; | ||
229 | } | ||
154 | } | 230 | } |
155 | 231 | ||
156 | /// <summary> | 232 | /// <summary> |
@@ -203,14 +279,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
203 | 279 | ||
204 | lock (m_agentsInTransit) | 280 | lock (m_agentsInTransit) |
205 | { | 281 | { |
206 | if (!IsInTransit(id)) | 282 | AgentTransferState? currentState = GetAgentTransferState(id); |
283 | |||
284 | if (currentState == null) | ||
207 | throw new Exception( | 285 | throw new Exception( |
208 | string.Format( | 286 | string.Format( |
209 | "Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit", | 287 | "Asked to wait for destination callback for agent with ID {0} in {1} but agent is not in transit", |
210 | id, m_mod.Scene.RegionInfo.RegionName)); | 288 | id, m_mod.Scene.RegionInfo.RegionName)); |
211 | 289 | ||
212 | AgentTransferState currentState = m_agentsInTransit[id]; | ||
213 | |||
214 | if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination) | 290 | if (currentState != AgentTransferState.Transferring && currentState != AgentTransferState.ReceivedAtDestination) |
215 | throw new Exception( | 291 | throw new Exception( |
216 | string.Format( | 292 | string.Format( |
@@ -222,8 +298,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
222 | 298 | ||
223 | // There should be no race condition here since no other code should be removing the agent transfer or | 299 | // There should be no race condition here since no other code should be removing the agent transfer or |
224 | // changing the state to another other than Transferring => ReceivedAtDestination. | 300 | // changing the state to another other than Transferring => ReceivedAtDestination. |
225 | while (m_agentsInTransit[id] != AgentTransferState.ReceivedAtDestination && count-- > 0) | 301 | |
302 | while (count-- > 0) | ||
226 | { | 303 | { |
304 | lock (m_agentsInTransit) | ||
305 | { | ||
306 | if (m_agentsInTransit[id] == AgentTransferState.ReceivedAtDestination) | ||
307 | break; | ||
308 | } | ||
309 | |||
227 | // m_log.Debug(" >>> Waiting... " + count); | 310 | // m_log.Debug(" >>> Waiting... " + count); |
228 | Thread.Sleep(100); | 311 | Thread.Sleep(100); |
229 | } | 312 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index f3a0b01..d372c0e 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
199 | 199 | ||
200 | public override void RemoveRegion(Scene scene) | 200 | public override void RemoveRegion(Scene scene) |
201 | { | 201 | { |
202 | base.AddRegion(scene); | 202 | base.RemoveRegion(scene); |
203 | 203 | ||
204 | if (m_Enabled) | 204 | if (m_Enabled) |
205 | scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this); | 205 | scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this); |
@@ -212,11 +212,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
212 | protected override GridRegion GetFinalDestination(GridRegion region) | 212 | protected override GridRegion GetFinalDestination(GridRegion region) |
213 | { | 213 | { |
214 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); | 214 | int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); |
215 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); | 215 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionName, flags); |
216 | 216 | ||
217 | if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) | 217 | if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) |
218 | { | 218 | { |
219 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); | 219 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region is hyperlink"); |
220 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); | 220 | GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); |
221 | if (real_destination != null) | 221 | if (real_destination != null) |
222 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: GetFinalDestination serveruri -> {0}", real_destination.ServerURI); | 222 | m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: GetFinalDestination serveruri -> {0}", real_destination.ServerURI); |
diff --git a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs index 4004135..b9786ae 100644 --- a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs +++ b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using OpenSim.Region.Framework.Interfaces; | 30 | using OpenSim.Region.Framework.Interfaces; |
31 | using OpenMetaverse; | ||
31 | 32 | ||
32 | namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander | 33 | namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander |
33 | { | 34 | { |
@@ -152,6 +153,9 @@ namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander | |||
152 | case "Boolean": | 153 | case "Boolean": |
153 | m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); | 154 | m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); |
154 | break; | 155 | break; |
156 | case "UUID": | ||
157 | m_args[i].ArgumentValue = UUID.Parse(arg.ToString()); | ||
158 | break; | ||
155 | default: | 159 | default: |
156 | Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); | 160 | Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); |
157 | break; | 161 | break; |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index f8ec6de..7871eda 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
71 | 71 | ||
72 | #region Internal functions | 72 | #region Internal functions |
73 | 73 | ||
74 | public AssetMetadata FetchMetadata(string url, UUID assetID) | 74 | private AssetMetadata FetchMetadata(string url, UUID assetID) |
75 | { | 75 | { |
76 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 76 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
77 | url = url + "/"; | 77 | url = url + "/"; |
@@ -86,6 +86,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
86 | return meta; | 86 | return meta; |
87 | } | 87 | } |
88 | 88 | ||
89 | private AssetBase FetchAsset(string url, UUID assetID) | ||
90 | { | ||
91 | // Test if it's already here | ||
92 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); | ||
93 | if (asset == null) | ||
94 | { | ||
95 | if (!url.EndsWith("/") && !url.EndsWith("=")) | ||
96 | url = url + "/"; | ||
97 | |||
98 | asset = m_scene.AssetService.Get(url + assetID.ToString()); | ||
99 | |||
100 | //if (asset != null) | ||
101 | // m_log.DebugFormat("[HG ASSET MAPPER]: Fetched asset {0} of type {1} from {2} ", assetID, asset.Metadata.Type, url); | ||
102 | //else | ||
103 | // m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetch asset {0} from {1} ", assetID, url); | ||
104 | |||
105 | } | ||
106 | |||
107 | return asset; | ||
108 | } | ||
109 | |||
89 | public bool PostAsset(string url, AssetBase asset) | 110 | public bool PostAsset(string url, AssetBase asset) |
90 | { | 111 | { |
91 | if (asset != null) | 112 | if (asset != null) |
@@ -228,11 +249,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
228 | if (meta == null) | 249 | if (meta == null) |
229 | return; | 250 | return; |
230 | 251 | ||
231 | // The act of gathering UUIDs downloads the assets from the remote server | 252 | // The act of gathering UUIDs downloads some assets from the remote server |
253 | // but not all... | ||
232 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | 254 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); |
233 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); | 255 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); |
234 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); | 256 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); |
235 | 257 | m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); | |
258 | bool success = true; | ||
259 | foreach (UUID uuid in ids.Keys) | ||
260 | if (FetchAsset(userAssetURL, uuid) == null) | ||
261 | success = false; | ||
262 | |||
263 | // maybe all pieces got here... | ||
264 | if (!success) | ||
265 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems getting item {0} from asset server {1}", assetID, userAssetURL); | ||
266 | else | ||
267 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL); | ||
236 | } | 268 | } |
237 | 269 | ||
238 | 270 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 964efda..b2b628d 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs | |||
@@ -88,12 +88,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
88 | IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; | 88 | IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; |
89 | if (thisModuleConfig != null) | 89 | if (thisModuleConfig != null) |
90 | { | 90 | { |
91 | // legacy configuration [obsolete] | 91 | m_HomeURI = Util.GetConfigVarFromSections<string>(source, "HomeURI", |
92 | m_HomeURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); | 92 | new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty); |
93 | // preferred | 93 | m_ThisGatekeeper = Util.GetConfigVarFromSections<string>(source, "GatekeeperURI", |
94 | m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); | 94 | new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty); |
95 | // Legacy. Renove soon! | ||
96 | m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", m_ThisGatekeeper); | ||
97 | |||
95 | m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); | 98 | m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); |
96 | m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); | ||
97 | m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); | 99 | m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); |
98 | } | 100 | } |
99 | else | 101 | else |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 6e5a4a5..5aad7f0 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | |||
@@ -47,6 +47,7 @@ using OpenMetaverse; | |||
47 | using log4net; | 47 | using log4net; |
48 | using Nini.Config; | 48 | using Nini.Config; |
49 | using Mono.Addins; | 49 | using Mono.Addins; |
50 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
50 | 51 | ||
51 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | 52 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess |
52 | { | 53 | { |
@@ -398,7 +399,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
398 | objectGroup.RootPart.NextOwnerMask &= | 399 | objectGroup.RootPart.NextOwnerMask &= |
399 | ((uint)PermissionMask.Copy | | 400 | ((uint)PermissionMask.Copy | |
400 | (uint)PermissionMask.Transfer | | 401 | (uint)PermissionMask.Transfer | |
401 | (uint)PermissionMask.Modify); | 402 | (uint)PermissionMask.Modify | |
403 | (uint)PermissionMask.Export); | ||
402 | objectGroup.RootPart.NextOwnerMask |= | 404 | objectGroup.RootPart.NextOwnerMask |= |
403 | (uint)PermissionMask.Move; | 405 | (uint)PermissionMask.Move; |
404 | 406 | ||
@@ -506,7 +508,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
506 | InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, | 508 | InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, |
507 | IClientAPI remoteClient) | 509 | IClientAPI remoteClient) |
508 | { | 510 | { |
509 | uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; | 511 | uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; |
510 | // For the porposes of inventory, an object is modify if the prims | 512 | // For the porposes of inventory, an object is modify if the prims |
511 | // are modify. This allows renaming an object that contains no | 513 | // are modify. This allows renaming an object that contains no |
512 | // mod items. | 514 | // mod items. |
@@ -555,6 +557,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
555 | (uint)PermissionMask.Transfer | | 557 | (uint)PermissionMask.Transfer | |
556 | (uint)PermissionMask.Modify | | 558 | (uint)PermissionMask.Modify | |
557 | (uint)PermissionMask.Move | | 559 | (uint)PermissionMask.Move | |
560 | (uint)PermissionMask.Export | | ||
558 | 7); // Preserve folded permissions | 561 | 7); // Preserve folded permissions |
559 | } | 562 | } |
560 | 563 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 21d8bd7..ad1a0e1 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs | |||
@@ -49,7 +49,7 @@ using OpenSim.Tests.Common.Mock; | |||
49 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | 49 | namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests |
50 | { | 50 | { |
51 | [TestFixture] | 51 | [TestFixture] |
52 | public class InventoryAccessModuleTests | 52 | public class InventoryAccessModuleTests : OpenSimTestCase |
53 | { | 53 | { |
54 | protected TestScene m_scene; | 54 | protected TestScene m_scene; |
55 | protected BasicInventoryAccessModule m_iam; | 55 | protected BasicInventoryAccessModule m_iam; |
@@ -57,8 +57,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | |||
57 | protected TestClient m_tc; | 57 | protected TestClient m_tc; |
58 | 58 | ||
59 | [SetUp] | 59 | [SetUp] |
60 | public void SetUp() | 60 | public override void SetUp() |
61 | { | 61 | { |
62 | base.SetUp(); | ||
63 | |||
62 | m_iam = new BasicInventoryAccessModule(); | 64 | m_iam = new BasicInventoryAccessModule(); |
63 | 65 | ||
64 | IConfigSource config = new IniConfigSource(); | 66 | IConfigSource config = new IniConfigSource(); |
@@ -107,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | |||
107 | item1.AssetID = asset1.FullID; | 109 | item1.AssetID = asset1.FullID; |
108 | item1.ID = item1Id; | 110 | item1.ID = item1Id; |
109 | InventoryFolderBase objsFolder | 111 | InventoryFolderBase objsFolder |
110 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0]; | 112 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; |
111 | item1.Folder = objsFolder.ID; | 113 | item1.Folder = objsFolder.ID; |
112 | m_scene.AddInventoryItem(item1); | 114 | m_scene.AddInventoryItem(item1); |
113 | 115 | ||
@@ -157,7 +159,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests | |||
157 | item1.AssetID = asset1.FullID; | 159 | item1.AssetID = asset1.FullID; |
158 | item1.ID = item1Id; | 160 | item1.ID = item1Id; |
159 | InventoryFolderBase objsFolder | 161 | InventoryFolderBase objsFolder |
160 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0]; | 162 | = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; |
161 | item1.Folder = objsFolder.ID; | 163 | item1.Folder = objsFolder.ID; |
162 | m_scene.AddInventoryItem(item1); | 164 | m_scene.AddInventoryItem(item1); |
163 | 165 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs index ec22146..d07cff4 100644 --- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs | |||
@@ -43,6 +43,7 @@ using OpenMetaverse; | |||
43 | using log4net; | 43 | using log4net; |
44 | using Mono.Addins; | 44 | using Mono.Addins; |
45 | using Nini.Config; | 45 | using Nini.Config; |
46 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
46 | 47 | ||
47 | namespace OpenSim.Region.CoreModules.Framework.Library | 48 | namespace OpenSim.Region.CoreModules.Framework.Library |
48 | { | 49 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index d84460a..64feec1 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | |||
@@ -33,6 +33,7 @@ using log4net; | |||
33 | using Nini.Config; | 33 | using Nini.Config; |
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
36 | using OpenSim.Framework.Monitoring; | ||
36 | using OpenSim.Framework.Servers; | 37 | using OpenSim.Framework.Servers; |
37 | using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts; | 38 | using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts; |
38 | using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors; | 39 | using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors; |
@@ -100,6 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
100 | "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage); | 101 | "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage); |
101 | 102 | ||
102 | AddMonitors(); | 103 | AddMonitors(); |
104 | RegisterStatsManagerRegionStatistics(); | ||
103 | } | 105 | } |
104 | 106 | ||
105 | public void RemoveRegion(Scene scene) | 107 | public void RemoveRegion(Scene scene) |
@@ -109,6 +111,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
109 | 111 | ||
110 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID); | 112 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID); |
111 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName)); | 113 | MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName)); |
114 | |||
115 | UnRegisterStatsManagerRegionStatistics(); | ||
116 | |||
112 | m_scene = null; | 117 | m_scene = null; |
113 | } | 118 | } |
114 | 119 | ||
@@ -399,6 +404,45 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring | |||
399 | { | 404 | { |
400 | m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")"); | 405 | m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")"); |
401 | } | 406 | } |
407 | |||
408 | private List<Stat> registeredStats = new List<Stat>(); | ||
409 | private void MakeStat(string pName, string pUnitName, Action<Stat> act) | ||
410 | { | ||
411 | Stat tempStat = new Stat(pName, pName, pName, pUnitName, "scene", m_scene.RegionInfo.RegionName, StatType.Pull, act, StatVerbosity.Info); | ||
412 | StatsManager.RegisterStat(tempStat); | ||
413 | registeredStats.Add(tempStat); | ||
414 | } | ||
415 | private void RegisterStatsManagerRegionStatistics() | ||
416 | { | ||
417 | MakeStat("RootAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootAgentCount(); }); | ||
418 | MakeStat("ChildAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetChildAgentCount(); }); | ||
419 | MakeStat("TotalPrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetTotalObjectsCount(); }); | ||
420 | MakeStat("ActivePrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetActiveObjectsCount(); }); | ||
421 | MakeStat("ActiveScripts", "scripts", (s) => { s.Value = m_scene.SceneGraph.GetActiveScriptsCount(); }); | ||
422 | |||
423 | MakeStat("TimeDilation", "sec/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[0]; }); | ||
424 | MakeStat("SimFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[1]; }); | ||
425 | MakeStat("PhysicsFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[2]; }); | ||
426 | MakeStat("AgentUpdates", "updates/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[3]; }); | ||
427 | MakeStat("FrameTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[8]; }); | ||
428 | MakeStat("NetTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[9]; }); | ||
429 | MakeStat("OtherTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[12]; }); | ||
430 | MakeStat("PhysicsTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[10]; }); | ||
431 | MakeStat("AgentTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[16]; }); | ||
432 | MakeStat("ImageTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[11]; }); | ||
433 | MakeStat("ScriptLines", "lines/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[20]; }); | ||
434 | MakeStat("SimSpareMS", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[21]; }); | ||
435 | } | ||
436 | |||
437 | private void UnRegisterStatsManagerRegionStatistics() | ||
438 | { | ||
439 | foreach (Stat stat in registeredStats) | ||
440 | { | ||
441 | StatsManager.DeregisterStat(stat); | ||
442 | stat.Dispose(); | ||
443 | } | ||
444 | registeredStats.Clear(); | ||
445 | } | ||
402 | 446 | ||
403 | } | 447 | } |
404 | } | 448 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs index fb74cc6..f3436d1 100644 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs | |||
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
57 | try | 57 | try |
58 | { | 58 | { |
59 | IConfig statConfig = source.Configs["Statistics.Binary"]; | 59 | IConfig statConfig = source.Configs["Statistics.Binary"]; |
60 | if (statConfig.Contains("enabled") && statConfig.GetBoolean("enabled")) | 60 | if (statConfig != null && statConfig.Contains("enabled") && statConfig.GetBoolean("enabled")) |
61 | { | 61 | { |
62 | if (statConfig.Contains("collect_region_stats")) | 62 | if (statConfig.Contains("collect_region_stats")) |
63 | { | 63 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs index fd8d5e3..2fe9026 100755 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs | |||
@@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
52 | private TimeSpan m_logFileLife; | 52 | private TimeSpan m_logFileLife; |
53 | private DateTime m_logFileEndTime; | 53 | private DateTime m_logFileEndTime; |
54 | private Object m_logFileWriteLock = new Object(); | 54 | private Object m_logFileWriteLock = new Object(); |
55 | private bool m_flushWrite; | ||
55 | 56 | ||
56 | // set externally when debugging. If let 'null', this does not write any error messages. | 57 | // set externally when debugging. If let 'null', this does not write any error messages. |
57 | public ILog ErrorLogger = null; | 58 | public ILog ErrorLogger = null; |
@@ -73,7 +74,9 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
73 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> | 74 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> |
74 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> | 75 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> |
75 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> | 76 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> |
76 | public LogWriter(string dir, string headr, int maxFileTime) | 77 | /// <param name="flushWrite">Whether to do a flush after every log write. Best left off but |
78 | /// if one is looking for a crash, this is a good thing to turn on.</param> | ||
79 | public LogWriter(string dir, string headr, int maxFileTime, bool flushWrite) | ||
77 | { | 80 | { |
78 | m_logDirectory = dir == null ? "." : dir; | 81 | m_logDirectory = dir == null ? "." : dir; |
79 | 82 | ||
@@ -86,8 +89,14 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
86 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); | 89 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); |
87 | m_logFileEndTime = DateTime.Now + m_logFileLife; | 90 | m_logFileEndTime = DateTime.Now + m_logFileLife; |
88 | 91 | ||
92 | m_flushWrite = flushWrite; | ||
93 | |||
89 | Enabled = true; | 94 | Enabled = true; |
90 | } | 95 | } |
96 | // Constructor that assumes flushWrite is off. | ||
97 | public LogWriter(string dir, string headr, int maxFileTime) : this(dir, headr, maxFileTime, false) | ||
98 | { | ||
99 | } | ||
91 | 100 | ||
92 | public void Dispose() | 101 | public void Dispose() |
93 | { | 102 | { |
@@ -127,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
127 | { | 136 | { |
128 | lock (m_logFileWriteLock) | 137 | lock (m_logFileWriteLock) |
129 | { | 138 | { |
130 | DateTime now = DateTime.Now; | 139 | DateTime now = DateTime.UtcNow; |
131 | if (m_logFile == null || now > m_logFileEndTime) | 140 | if (m_logFile == null || now > m_logFileEndTime) |
132 | { | 141 | { |
133 | if (m_logFile != null) | 142 | if (m_logFile != null) |
@@ -153,6 +162,8 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
153 | buff.Append(line); | 162 | buff.Append(line); |
154 | buff.Append("\r\n"); | 163 | buff.Append("\r\n"); |
155 | m_logFile.Write(buff.ToString()); | 164 | m_logFile.Write(buff.ToString()); |
165 | if (m_flushWrite) | ||
166 | m_logFile.Flush(); | ||
156 | } | 167 | } |
157 | } | 168 | } |
158 | } | 169 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 86e7004..77e8b00 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | |||
@@ -181,6 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
181 | 181 | ||
182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); | 182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); |
183 | 183 | ||
184 | // searhc the user accounts service | ||
184 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); | 185 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); |
185 | 186 | ||
186 | List<UserData> users = new List<UserData>(); | 187 | List<UserData> users = new List<UserData>(); |
@@ -196,6 +197,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
196 | } | 197 | } |
197 | } | 198 | } |
198 | 199 | ||
200 | // search the local cache | ||
201 | foreach (UserData data in m_UserCache.Values) | ||
202 | if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && | ||
203 | (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query))) | ||
204 | users.Add(data); | ||
205 | |||
199 | AddAdditionalUsers(avatarID, query, users); | 206 | AddAdditionalUsers(avatarID, query, users); |
200 | 207 | ||
201 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); | 208 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); |
@@ -433,6 +440,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
433 | public void AddUser(UUID uuid, string first, string last, string homeURL) | 440 | public void AddUser(UUID uuid, string first, string last, string homeURL) |
434 | { | 441 | { |
435 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); | 442 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); |
443 | if (homeURL == string.Empty) | ||
444 | return; | ||
445 | |||
436 | AddUser(uuid, homeURL + ";" + first + " " + last); | 446 | AddUser(uuid, homeURL + ";" + first + " " + last); |
437 | } | 447 | } |
438 | 448 | ||
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index ec94420..7b11658 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs | |||
@@ -52,8 +52,8 @@ namespace OpenSim.Region.CoreModules.Hypergrid | |||
52 | 52 | ||
53 | public override void Initialise(IConfigSource config) | 53 | public override void Initialise(IConfigSource config) |
54 | { | 54 | { |
55 | IConfig startupConfig = config.Configs["Startup"]; | 55 | if (Util.GetConfigVarFromSections<string>( |
56 | if (startupConfig.GetString("WorldMapModule", "WorldMap") == "HGWorldMap") | 56 | config, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap") |
57 | m_Enabled = true; | 57 | m_Enabled = true; |
58 | } | 58 | } |
59 | 59 | ||
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs index 5a8c4a2..bfe0383 100644 --- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs | |||
@@ -30,8 +30,8 @@ using Mono.Addins; | |||
30 | // Build Number | 30 | // Build Number |
31 | // Revision | 31 | // Revision |
32 | // | 32 | // |
33 | [assembly: AssemblyVersion("0.7.5.*")] | 33 | [assembly: AssemblyVersion("0.7.6.*")] |
34 | [assembly: AssemblyFileVersion("1.0.0.0")] | 34 | |
35 | 35 | ||
36 | [assembly: Addin("OpenSim.Region.CoreModules", "0.1")] | 36 | [assembly: Addin("OpenSim.Region.CoreModules", "0.1")] |
37 | [assembly: AddinDependency("OpenSim", "0.5")] | 37 | [assembly: AddinDependency("OpenSim", "0.5")] |
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 0276267..2b13a8b 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | |||
@@ -189,6 +189,45 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
189 | case (int)HttpRequestConstants.HTTP_VERIFY_CERT: | 189 | case (int)HttpRequestConstants.HTTP_VERIFY_CERT: |
190 | htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0); | 190 | htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0); |
191 | break; | 191 | break; |
192 | |||
193 | case (int)HttpRequestConstants.HTTP_VERBOSE_THROTTLE: | ||
194 | |||
195 | // TODO implement me | ||
196 | break; | ||
197 | |||
198 | case (int)HttpRequestConstants.HTTP_CUSTOM_HEADER: | ||
199 | //Parameters are in pairs and custom header takes | ||
200 | //arguments in pairs so adjust for header marker. | ||
201 | ++i; | ||
202 | |||
203 | //Maximum of 8 headers are allowed based on the | ||
204 | //Second Life documentation for llHTTPRequest. | ||
205 | for (int count = 1; count <= 8; ++count) | ||
206 | { | ||
207 | //Not enough parameters remaining for a header? | ||
208 | if (parms.Length - i < 2) | ||
209 | break; | ||
210 | |||
211 | //Have we reached the end of the list of headers? | ||
212 | //End is marked by a string with a single digit. | ||
213 | //We already know we have at least one parameter | ||
214 | //so it is safe to do this check at top of loop. | ||
215 | if (Char.IsDigit(parms[i][0])) | ||
216 | break; | ||
217 | |||
218 | if (htc.HttpCustomHeaders == null) | ||
219 | htc.HttpCustomHeaders = new List<string>(); | ||
220 | |||
221 | htc.HttpCustomHeaders.Add(parms[i]); | ||
222 | htc.HttpCustomHeaders.Add(parms[i+1]); | ||
223 | |||
224 | i += 2; | ||
225 | } | ||
226 | break; | ||
227 | |||
228 | case (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE: | ||
229 | htc.HttpPragmaNoCache = (int.Parse(parms[i + 1]) != 0); | ||
230 | break; | ||
192 | } | 231 | } |
193 | } | 232 | } |
194 | } | 233 | } |
@@ -353,9 +392,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
353 | // public const int HTTP_METHOD = 0; | 392 | // public const int HTTP_METHOD = 0; |
354 | // public const int HTTP_MIMETYPE = 1; | 393 | // public const int HTTP_MIMETYPE = 1; |
355 | // public const int HTTP_VERIFY_CERT = 3; | 394 | // public const int HTTP_VERIFY_CERT = 3; |
395 | // public const int HTTP_VERBOSE_THROTTLE = 4; | ||
396 | // public const int HTTP_CUSTOM_HEADER = 5; | ||
397 | // public const int HTTP_PRAGMA_NO_CACHE = 6; | ||
356 | private bool _finished; | 398 | private bool _finished; |
357 | public bool Finished | 399 | public bool Finished |
358 | { | 400 | { |
359 | get { return _finished; } | 401 | get { return _finished; } |
360 | } | 402 | } |
361 | // public int HttpBodyMaxLen = 2048; // not implemented | 403 | // public int HttpBodyMaxLen = 2048; // not implemented |
@@ -367,9 +409,14 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
367 | public bool HttpVerifyCert = true; | 409 | public bool HttpVerifyCert = true; |
368 | public IWorkItemResult WorkItem = null; | 410 | public IWorkItemResult WorkItem = null; |
369 | 411 | ||
412 | //public bool HttpVerboseThrottle = true; // not implemented | ||
413 | public List<string> HttpCustomHeaders = null; | ||
414 | public bool HttpPragmaNoCache = true; | ||
415 | private Thread httpThread; | ||
416 | |||
370 | // Request info | 417 | // Request info |
371 | private UUID _itemID; | 418 | private UUID _itemID; |
372 | public UUID ItemID | 419 | public UUID ItemID |
373 | { | 420 | { |
374 | get { return _itemID; } | 421 | get { return _itemID; } |
375 | set { _itemID = value; } | 422 | set { _itemID = value; } |
@@ -385,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
385 | public string proxyexcepts; | 432 | public string proxyexcepts; |
386 | public string OutboundBody; | 433 | public string OutboundBody; |
387 | private UUID _reqID; | 434 | private UUID _reqID; |
388 | public UUID ReqID | 435 | public UUID ReqID |
389 | { | 436 | { |
390 | get { return _reqID; } | 437 | get { return _reqID; } |
391 | set { _reqID = value; } | 438 | set { _reqID = value; } |
@@ -434,20 +481,34 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
434 | Request.Method = HttpMethod; | 481 | Request.Method = HttpMethod; |
435 | Request.ContentType = HttpMIMEType; | 482 | Request.ContentType = HttpMIMEType; |
436 | 483 | ||
437 | if(!HttpVerifyCert) | 484 | if (!HttpVerifyCert) |
438 | { | 485 | { |
439 | // We could hijack Connection Group Name to identify | 486 | // We could hijack Connection Group Name to identify |
440 | // a desired security exception. But at the moment we'll use a dummy header instead. | 487 | // a desired security exception. But at the moment we'll use a dummy header instead. |
441 | Request.Headers.Add("NoVerifyCert", "true"); | 488 | Request.Headers.Add("NoVerifyCert", "true"); |
442 | } | 489 | } |
443 | if (proxyurl != null && proxyurl.Length > 0) | 490 | // else |
491 | // { | ||
492 | // Request.ConnectionGroupName="Verify"; | ||
493 | // } | ||
494 | if (!HttpPragmaNoCache) | ||
495 | { | ||
496 | Request.Headers.Add("Pragma", "no-cache"); | ||
497 | } | ||
498 | if (HttpCustomHeaders != null) | ||
444 | { | 499 | { |
445 | if (proxyexcepts != null && proxyexcepts.Length > 0) | 500 | for (int i = 0; i < HttpCustomHeaders.Count; i += 2) |
501 | Request.Headers.Add(HttpCustomHeaders[i], | ||
502 | HttpCustomHeaders[i+1]); | ||
503 | } | ||
504 | if (proxyurl != null && proxyurl.Length > 0) | ||
505 | { | ||
506 | if (proxyexcepts != null && proxyexcepts.Length > 0) | ||
446 | { | 507 | { |
447 | string[] elist = proxyexcepts.Split(';'); | 508 | string[] elist = proxyexcepts.Split(';'); |
448 | Request.Proxy = new WebProxy(proxyurl, true, elist); | 509 | Request.Proxy = new WebProxy(proxyurl, true, elist); |
449 | } | 510 | } |
450 | else | 511 | else |
451 | { | 512 | { |
452 | Request.Proxy = new WebProxy(proxyurl, true); | 513 | Request.Proxy = new WebProxy(proxyurl, true); |
453 | } | 514 | } |
@@ -460,7 +521,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
460 | Request.Headers[entry.Key] = entry.Value; | 521 | Request.Headers[entry.Key] = entry.Value; |
461 | 522 | ||
462 | // Encode outbound data | 523 | // Encode outbound data |
463 | if (OutboundBody.Length > 0) | 524 | if (OutboundBody.Length > 0) |
464 | { | 525 | { |
465 | byte[] data = Util.UTF8.GetBytes(OutboundBody); | 526 | byte[] data = Util.UTF8.GetBytes(OutboundBody); |
466 | 527 | ||
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index da59eab..f2922d6 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | |||
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
50 | public string url; | 50 | public string url; |
51 | public UUID urlcode; | 51 | public UUID urlcode; |
52 | public Dictionary<UUID, RequestData> requests; | 52 | public Dictionary<UUID, RequestData> requests; |
53 | public bool isSsl; | ||
53 | } | 54 | } |
54 | 55 | ||
55 | public class RequestData | 56 | public class RequestData |
@@ -83,20 +84,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
83 | private Dictionary<string, UrlData> m_UrlMap = | 84 | private Dictionary<string, UrlData> m_UrlMap = |
84 | new Dictionary<string, UrlData>(); | 85 | new Dictionary<string, UrlData>(); |
85 | 86 | ||
86 | /// <summary> | 87 | private uint m_HttpsPort = 0; |
87 | /// Maximum number of external urls that can be set up by this module. | ||
88 | /// </summary> | ||
89 | private int m_TotalUrls = 15000; | ||
90 | |||
91 | private uint https_port = 0; | ||
92 | private IHttpServer m_HttpServer = null; | 88 | private IHttpServer m_HttpServer = null; |
93 | private IHttpServer m_HttpsServer = null; | 89 | private IHttpServer m_HttpsServer = null; |
94 | 90 | ||
95 | private string m_ExternalHostNameForLSL = ""; | 91 | public string ExternalHostNameForLSL { get; private set; } |
96 | public string ExternalHostNameForLSL | 92 | |
97 | { | 93 | /// <summary> |
98 | get { return m_ExternalHostNameForLSL; } | 94 | /// The default maximum number of urls |
99 | } | 95 | /// </summary> |
96 | public const int DefaultTotalUrls = 15000; | ||
97 | |||
98 | /// <summary> | ||
99 | /// Maximum number of external urls that can be set up by this module. | ||
100 | /// </summary> | ||
101 | public int TotalUrls { get; set; } | ||
100 | 102 | ||
101 | public Type ReplaceableInterface | 103 | public Type ReplaceableInterface |
102 | { | 104 | { |
@@ -110,17 +112,27 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
110 | 112 | ||
111 | public void Initialise(IConfigSource config) | 113 | public void Initialise(IConfigSource config) |
112 | { | 114 | { |
113 | m_ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", System.Environment.MachineName); | 115 | IConfig networkConfig = config.Configs["Network"]; |
114 | bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener",false); | 116 | |
115 | if (ssl_enabled) | 117 | if (networkConfig != null) |
116 | { | 118 | { |
117 | https_port = (uint) config.Configs["Network"].GetInt("https_port",0); | 119 | ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", null); |
120 | |||
121 | bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener", false); | ||
122 | |||
123 | if (ssl_enabled) | ||
124 | m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort); | ||
118 | } | 125 | } |
119 | 126 | ||
127 | if (ExternalHostNameForLSL == null) | ||
128 | ExternalHostNameForLSL = System.Environment.MachineName; | ||
129 | |||
120 | IConfig llFunctionsConfig = config.Configs["LL-Functions"]; | 130 | IConfig llFunctionsConfig = config.Configs["LL-Functions"]; |
121 | 131 | ||
122 | if (llFunctionsConfig != null) | 132 | if (llFunctionsConfig != null) |
123 | m_TotalUrls = llFunctionsConfig.GetInt("max_external_urls_per_simulator", m_TotalUrls); | 133 | TotalUrls = llFunctionsConfig.GetInt("max_external_urls_per_simulator", DefaultTotalUrls); |
134 | else | ||
135 | TotalUrls = DefaultTotalUrls; | ||
124 | } | 136 | } |
125 | 137 | ||
126 | public void PostInitialise() | 138 | public void PostInitialise() |
@@ -136,9 +148,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
136 | m_HttpServer = MainServer.Instance; | 148 | m_HttpServer = MainServer.Instance; |
137 | // | 149 | // |
138 | // We can use the https if it is enabled | 150 | // We can use the https if it is enabled |
139 | if (https_port > 0) | 151 | if (m_HttpsPort > 0) |
140 | { | 152 | { |
141 | m_HttpsServer = MainServer.GetHttpServer(https_port); | 153 | m_HttpsServer = MainServer.GetHttpServer(m_HttpsPort); |
142 | } | 154 | } |
143 | } | 155 | } |
144 | 156 | ||
@@ -171,12 +183,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
171 | 183 | ||
172 | lock (m_UrlMap) | 184 | lock (m_UrlMap) |
173 | { | 185 | { |
174 | if (m_UrlMap.Count >= m_TotalUrls) | 186 | if (m_UrlMap.Count >= TotalUrls) |
175 | { | 187 | { |
176 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 188 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); |
177 | return urlcode; | 189 | return urlcode; |
178 | } | 190 | } |
179 | string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString(); | 191 | string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString(); |
180 | 192 | ||
181 | UrlData urlData = new UrlData(); | 193 | UrlData urlData = new UrlData(); |
182 | urlData.hostID = host.UUID; | 194 | urlData.hostID = host.UUID; |
@@ -184,6 +196,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
184 | urlData.engine = engine; | 196 | urlData.engine = engine; |
185 | urlData.url = url; | 197 | urlData.url = url; |
186 | urlData.urlcode = urlcode; | 198 | urlData.urlcode = urlcode; |
199 | urlData.isSsl = false; | ||
187 | urlData.requests = new Dictionary<UUID, RequestData>(); | 200 | urlData.requests = new Dictionary<UUID, RequestData>(); |
188 | 201 | ||
189 | m_UrlMap[url] = urlData; | 202 | m_UrlMap[url] = urlData; |
@@ -216,12 +229,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
216 | 229 | ||
217 | lock (m_UrlMap) | 230 | lock (m_UrlMap) |
218 | { | 231 | { |
219 | if (m_UrlMap.Count >= m_TotalUrls) | 232 | if (m_UrlMap.Count >= TotalUrls) |
220 | { | 233 | { |
221 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); | 234 | engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); |
222 | return urlcode; | 235 | return urlcode; |
223 | } | 236 | } |
224 | string url = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString(); | 237 | string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString(); |
225 | 238 | ||
226 | UrlData urlData = new UrlData(); | 239 | UrlData urlData = new UrlData(); |
227 | urlData.hostID = host.UUID; | 240 | urlData.hostID = host.UUID; |
@@ -229,6 +242,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
229 | urlData.engine = engine; | 242 | urlData.engine = engine; |
230 | urlData.url = url; | 243 | urlData.url = url; |
231 | urlData.urlcode = urlcode; | 244 | urlData.urlcode = urlcode; |
245 | urlData.isSsl = true; | ||
232 | urlData.requests = new Dictionary<UUID, RequestData>(); | 246 | urlData.requests = new Dictionary<UUID, RequestData>(); |
233 | 247 | ||
234 | 248 | ||
@@ -301,6 +315,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
301 | UrlData urlData = m_RequestMap[request]; | 315 | UrlData urlData = m_RequestMap[request]; |
302 | if (!urlData.requests[request].responseSent) | 316 | if (!urlData.requests[request].responseSent) |
303 | { | 317 | { |
318 | string responseBody = body; | ||
319 | if (urlData.requests[request].responseType.Equals("text/plain")) | ||
320 | { | ||
321 | string value; | ||
322 | if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) | ||
323 | { | ||
324 | if (value != null && value.IndexOf("MSIE") >= 0) | ||
325 | { | ||
326 | // wrap the html escaped response if the target client is IE | ||
327 | // It ignores "text/plain" if the body is html | ||
328 | responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | |||
304 | urlData.requests[request].responseCode = status; | 333 | urlData.requests[request].responseCode = status; |
305 | urlData.requests[request].responseBody = body; | 334 | urlData.requests[request].responseBody = body; |
306 | //urlData.requests[request].ev.Set(); | 335 | //urlData.requests[request].ev.Set(); |
@@ -336,7 +365,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
336 | 365 | ||
337 | public int GetFreeUrls() | 366 | public int GetFreeUrls() |
338 | { | 367 | { |
339 | return m_TotalUrls - m_UrlMap.Count; | 368 | lock (m_UrlMap) |
369 | return TotalUrls - m_UrlMap.Count; | ||
340 | } | 370 | } |
341 | 371 | ||
342 | public void ScriptRemoved(UUID itemID) | 372 | public void ScriptRemoved(UUID itemID) |
@@ -394,7 +424,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
394 | 424 | ||
395 | private void RemoveUrl(UrlData data) | 425 | private void RemoveUrl(UrlData data) |
396 | { | 426 | { |
397 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); | 427 | if (data.isSsl) |
428 | m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/"); | ||
429 | else | ||
430 | m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); | ||
398 | } | 431 | } |
399 | 432 | ||
400 | private Hashtable NoEvents(UUID requestID, UUID sessionID) | 433 | private Hashtable NoEvents(UUID requestID, UUID sessionID) |
@@ -527,7 +560,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
527 | { | 560 | { |
528 | Hashtable headers = (Hashtable)request["headers"]; | 561 | Hashtable headers = (Hashtable)request["headers"]; |
529 | 562 | ||
530 | // string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; | 563 | // string uri_full = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; |
531 | 564 | ||
532 | int pos1 = uri.IndexOf("/");// /lslhttp | 565 | int pos1 = uri.IndexOf("/");// /lslhttp |
533 | int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ | 566 | int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ |
@@ -543,10 +576,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp | |||
543 | UrlData url = null; | 576 | UrlData url = null; |
544 | string urlkey; | 577 | string urlkey; |
545 | if (!is_ssl) | 578 | if (!is_ssl) |
546 | urlkey = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; | 579 | urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; |
547 | //m_UrlMap[]; | 580 | //m_UrlMap[]; |
548 | else | 581 | else |
549 | urlkey = "https://" + m_ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; | 582 | urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; |
550 | 583 | ||
551 | if (m_UrlMap.ContainsKey(urlkey)) | 584 | if (m_UrlMap.ContainsKey(urlkey)) |
552 | { | 585 | { |
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index f6e1d39..fccf053 100644 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | |||
@@ -41,7 +41,7 @@ using System.Linq.Expressions; | |||
41 | namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms | 41 | namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms |
42 | { | 42 | { |
43 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] | 43 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] |
44 | class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms | 44 | public class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms |
45 | { | 45 | { |
46 | private static readonly ILog m_log = | 46 | private static readonly ILog m_log = |
47 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 47 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
@@ -262,6 +262,8 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms | |||
262 | return "modInvokeR"; | 262 | return "modInvokeR"; |
263 | else if (sid.ReturnType == typeof(object[])) | 263 | else if (sid.ReturnType == typeof(object[])) |
264 | return "modInvokeL"; | 264 | return "modInvokeL"; |
265 | else if (sid.ReturnType == typeof(void)) | ||
266 | return "modInvokeN"; | ||
265 | 267 | ||
266 | m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); | 268 | m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); |
267 | } | 269 | } |
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index f395441..2fc89fc 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -516,6 +516,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
516 | foreach (string line in GetLines(data, dataDelim)) | 516 | foreach (string line in GetLines(data, dataDelim)) |
517 | { | 517 | { |
518 | string nextLine = line.Trim(); | 518 | string nextLine = line.Trim(); |
519 | |||
520 | // m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine); | ||
521 | |||
519 | //replace with switch, or even better, do some proper parsing | 522 | //replace with switch, or even better, do some proper parsing |
520 | if (nextLine.StartsWith("MoveTo")) | 523 | if (nextLine.StartsWith("MoveTo")) |
521 | { | 524 | { |
@@ -829,6 +832,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
829 | float y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); | 832 | float y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); |
830 | PointF point = new PointF(x, y); | 833 | PointF point = new PointF(x, y); |
831 | points[i / 2] = point; | 834 | points[i / 2] = point; |
835 | |||
836 | // m_log.DebugFormat("[VECTOR RENDER MODULE]: Got point {0}", points[i / 2]); | ||
832 | } | 837 | } |
833 | } | 838 | } |
834 | } | 839 | } |
@@ -838,13 +843,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
838 | try | 843 | try |
839 | { | 844 | { |
840 | WebRequest request = HttpWebRequest.Create(url); | 845 | WebRequest request = HttpWebRequest.Create(url); |
841 | //Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. | 846 | |
842 | //Ckrinke Stream str = null; | 847 | using (HttpWebResponse response = (HttpWebResponse)(request).GetResponse()) |
843 | HttpWebResponse response = (HttpWebResponse)(request).GetResponse(); | ||
844 | if (response.StatusCode == HttpStatusCode.OK) | ||
845 | { | 848 | { |
846 | Bitmap image = new Bitmap(response.GetResponseStream()); | 849 | if (response.StatusCode == HttpStatusCode.OK) |
847 | return image; | 850 | { |
851 | using (Stream s = response.GetResponseStream()) | ||
852 | { | ||
853 | Bitmap image = new Bitmap(s); | ||
854 | return image; | ||
855 | } | ||
856 | } | ||
848 | } | 857 | } |
849 | } | 858 | } |
850 | catch { } | 859 | catch { } |
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index 385f5ad..cbffca7 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs | |||
@@ -111,13 +111,15 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC | |||
111 | m_rpcPending = new Dictionary<UUID, RPCRequestInfo>(); | 111 | m_rpcPending = new Dictionary<UUID, RPCRequestInfo>(); |
112 | m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>(); | 112 | m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>(); |
113 | m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>(); | 113 | m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>(); |
114 | 114 | if (config.Configs["XMLRPC"] != null) | |
115 | try | ||
116 | { | ||
117 | m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort); | ||
118 | } | ||
119 | catch (Exception) | ||
120 | { | 115 | { |
116 | try | ||
117 | { | ||
118 | m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort); | ||
119 | } | ||
120 | catch (Exception) | ||
121 | { | ||
122 | } | ||
121 | } | 123 | } |
122 | } | 124 | } |
123 | 125 | ||
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index 5836eb9..b61062f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs | |||
@@ -75,7 +75,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage | |||
75 | public void Close() { } | 75 | public void Close() { } |
76 | public void PostInitialise() { } | 76 | public void PostInitialise() { } |
77 | 77 | ||
78 | |||
79 | ///<summary> | 78 | ///<summary> |
80 | /// | 79 | /// |
81 | ///</summary> | 80 | ///</summary> |
@@ -136,7 +135,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage | |||
136 | ///</summary> | 135 | ///</summary> |
137 | public void AddRegion(Scene scene) | 136 | public void AddRegion(Scene scene) |
138 | { | 137 | { |
139 | if (! m_enabled) | 138 | if (!m_enabled) |
140 | return; | 139 | return; |
141 | 140 | ||
142 | // Every shared region module has to maintain an indepedent list of | 141 | // Every shared region module has to maintain an indepedent list of |
@@ -209,6 +208,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage | |||
209 | 208 | ||
210 | using (Image mapTile = tileGenerator.CreateMapTile()) | 209 | using (Image mapTile = tileGenerator.CreateMapTile()) |
211 | { | 210 | { |
211 | // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there | ||
212 | // is no static map tile. | ||
213 | if (mapTile == null) | ||
214 | return; | ||
215 | |||
212 | using (MemoryStream stream = new MemoryStream()) | 216 | using (MemoryStream stream = new MemoryStream()) |
213 | { | 217 | { |
214 | mapTile.Save(stream, ImageFormat.Jpeg); | 218 | mapTile.Save(stream, ImageFormat.Jpeg); |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs index 32e47f9..69bac82 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs | |||
@@ -35,7 +35,6 @@ using NUnit.Framework; | |||
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
37 | using Nini.Config; | 37 | using Nini.Config; |
38 | |||
39 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; | 38 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; |
40 | using OpenSim.Region.Framework.Scenes; | 39 | using OpenSim.Region.Framework.Scenes; |
41 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; | 40 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; |
@@ -44,11 +43,14 @@ using OpenSim.Tests.Common; | |||
44 | namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests | 43 | namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests |
45 | { | 44 | { |
46 | [TestFixture] | 45 | [TestFixture] |
47 | public class PresenceConnectorsTests | 46 | public class PresenceConnectorsTests : OpenSimTestCase |
48 | { | 47 | { |
49 | LocalPresenceServicesConnector m_LocalConnector; | 48 | LocalPresenceServicesConnector m_LocalConnector; |
50 | private void SetUp() | 49 | |
50 | public override void SetUp() | ||
51 | { | 51 | { |
52 | base.SetUp(); | ||
53 | |||
52 | IConfigSource config = new IniConfigSource(); | 54 | IConfigSource config = new IniConfigSource(); |
53 | config.AddConfig("Modules"); | 55 | config.AddConfig("Modules"); |
54 | config.AddConfig("PresenceService"); | 56 | config.AddConfig("PresenceService"); |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index b485194..8b8bb37 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs | |||
@@ -219,12 +219,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
219 | { | 219 | { |
220 | // m_log.DebugFormat( | 220 | // m_log.DebugFormat( |
221 | // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", | 221 | // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", |
222 | // s.RegionInfo.RegionName, destination.RegionHandle); | 222 | // destination.RegionName, destination.RegionID); |
223 | 223 | ||
224 | return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); | 224 | return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); |
225 | } | 225 | } |
226 | 226 | ||
227 | // m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle); | 227 | // m_log.DebugFormat( |
228 | // "[LOCAL COMMS]: Did not find region {0} {1} for ChildAgentUpdate", | ||
229 | // destination.RegionName, destination.RegionID); | ||
230 | |||
228 | return false; | 231 | return false; |
229 | } | 232 | } |
230 | 233 | ||
@@ -239,7 +242,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
239 | // note that we really don't need the GridRegion for this call | 242 | // note that we really don't need the GridRegion for this call |
240 | foreach (Scene s in m_scenes.Values) | 243 | foreach (Scene s in m_scenes.Values) |
241 | { | 244 | { |
242 | //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); | 245 | // m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); |
243 | s.IncomingChildAgentDataUpdate(cAgentData); | 246 | s.IncomingChildAgentDataUpdate(cAgentData); |
244 | } | 247 | } |
245 | 248 | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index ade5e76..fcfdf7c 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | |||
@@ -570,13 +570,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
570 | 570 | ||
571 | // Validate User and Group UUID's | 571 | // Validate User and Group UUID's |
572 | 572 | ||
573 | if (!ResolveUserUuid(scene, parcel.OwnerID)) | 573 | if (parcel.IsGroupOwned) |
574 | parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; | 574 | { |
575 | 575 | if (!ResolveGroupUuid(parcel.GroupID)) | |
576 | if (!ResolveGroupUuid(parcel.GroupID)) | 576 | { |
577 | parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; | ||
578 | parcel.GroupID = UUID.Zero; | ||
579 | parcel.IsGroupOwned = false; | ||
580 | } | ||
581 | } | ||
582 | else | ||
577 | { | 583 | { |
578 | parcel.GroupID = UUID.Zero; | 584 | if (!ResolveUserUuid(scene, parcel.OwnerID)) |
579 | parcel.IsGroupOwned = false; | 585 | parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; |
586 | |||
587 | if (!ResolveGroupUuid(parcel.GroupID)) | ||
588 | parcel.GroupID = UUID.Zero; | ||
580 | } | 589 | } |
581 | 590 | ||
582 | List<LandAccessEntry> accessList = new List<LandAccessEntry>(); | 591 | List<LandAccessEntry> accessList = new List<LandAccessEntry>(); |
@@ -589,8 +598,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
589 | parcel.ParcelAccessList = accessList; | 598 | parcel.ParcelAccessList = accessList; |
590 | 599 | ||
591 | // m_log.DebugFormat( | 600 | // m_log.DebugFormat( |
592 | // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", | 601 | // "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}", |
593 | // parcel.Name, parcel.LocalID, parcel.Area); | 602 | // parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area); |
594 | 603 | ||
595 | landData.Add(parcel); | 604 | landData.Add(parcel); |
596 | } | 605 | } |
@@ -613,13 +622,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
613 | /// <returns></returns> | 622 | /// <returns></returns> |
614 | private bool ResolveUserUuid(Scene scene, UUID uuid) | 623 | private bool ResolveUserUuid(Scene scene, UUID uuid) |
615 | { | 624 | { |
616 | if (!m_validUserUuids.ContainsKey(uuid)) | 625 | lock (m_validUserUuids) |
617 | { | 626 | { |
618 | UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); | 627 | if (!m_validUserUuids.ContainsKey(uuid)) |
619 | m_validUserUuids.Add(uuid, account != null); | 628 | { |
620 | } | 629 | // Note: we call GetUserAccount() inside the lock because this UserID is likely |
630 | // to occur many times, and we only want to query the users service once. | ||
631 | UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); | ||
632 | m_validUserUuids.Add(uuid, account != null); | ||
633 | } | ||
621 | 634 | ||
622 | return m_validUserUuids[uuid]; | 635 | return m_validUserUuids[uuid]; |
636 | } | ||
623 | } | 637 | } |
624 | 638 | ||
625 | /// <summary> | 639 | /// <summary> |
@@ -632,19 +646,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
632 | if (uuid == UUID.Zero) | 646 | if (uuid == UUID.Zero) |
633 | return true; // this means the object has no group | 647 | return true; // this means the object has no group |
634 | 648 | ||
635 | if (!m_validGroupUuids.ContainsKey(uuid)) | 649 | lock (m_validGroupUuids) |
636 | { | 650 | { |
637 | bool exists; | 651 | if (!m_validGroupUuids.ContainsKey(uuid)) |
638 | 652 | { | |
639 | if (m_groupsModule == null) | 653 | bool exists; |
640 | exists = false; | 654 | if (m_groupsModule == null) |
641 | else | 655 | { |
642 | exists = (m_groupsModule.GetGroupRecord(uuid) != null); | 656 | exists = false; |
657 | } | ||
658 | else | ||
659 | { | ||
660 | // Note: we call GetGroupRecord() inside the lock because this GroupID is likely | ||
661 | // to occur many times, and we only want to query the groups service once. | ||
662 | exists = (m_groupsModule.GetGroupRecord(uuid) != null); | ||
663 | } | ||
664 | m_validGroupUuids.Add(uuid, exists); | ||
665 | } | ||
643 | 666 | ||
644 | m_validGroupUuids.Add(uuid, exists); | 667 | return m_validGroupUuids[uuid]; |
645 | } | 668 | } |
646 | |||
647 | return m_validGroupUuids[uuid]; | ||
648 | } | 669 | } |
649 | 670 | ||
650 | /// Load an asset | 671 | /// Load an asset |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs index d751b1c..a990898 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs | |||
@@ -44,6 +44,7 @@ using Ionic.Zlib; | |||
44 | using GZipStream = Ionic.Zlib.GZipStream; | 44 | using GZipStream = Ionic.Zlib.GZipStream; |
45 | using CompressionMode = Ionic.Zlib.CompressionMode; | 45 | using CompressionMode = Ionic.Zlib.CompressionMode; |
46 | using OpenSim.Framework.Serialization.External; | 46 | using OpenSim.Framework.Serialization.External; |
47 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
47 | 48 | ||
48 | namespace OpenSim.Region.CoreModules.World.Archiver | 49 | namespace OpenSim.Region.CoreModules.World.Archiver |
49 | { | 50 | { |
@@ -167,7 +168,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
167 | } | 168 | } |
168 | scenesGroup.CalcSceneLocations(); | 169 | scenesGroup.CalcSceneLocations(); |
169 | 170 | ||
170 | |||
171 | m_archiveWriter = new TarArchiveWriter(m_saveStream); | 171 | m_archiveWriter = new TarArchiveWriter(m_saveStream); |
172 | 172 | ||
173 | try | 173 | try |
@@ -216,7 +216,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
216 | } | 216 | } |
217 | } | 217 | } |
218 | 218 | ||
219 | |||
220 | private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) | 219 | private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) |
221 | { | 220 | { |
222 | m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); | 221 | m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); |
@@ -540,7 +539,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
540 | xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); | 539 | xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); |
541 | } | 540 | } |
542 | 541 | ||
543 | |||
544 | protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir) | 542 | protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir) |
545 | { | 543 | { |
546 | if (regionDir != string.Empty) | 544 | if (regionDir != string.Empty) |
@@ -560,8 +558,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
560 | foreach (ILandObject lo in landObjects) | 558 | foreach (ILandObject lo in landObjects) |
561 | { | 559 | { |
562 | LandData landData = lo.LandData; | 560 | LandData landData = lo.LandData; |
563 | string landDataPath = String.Format("{0}{1}{2}.xml", | 561 | string landDataPath |
564 | regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); | 562 | = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData)); |
565 | m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); | 563 | m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); |
566 | } | 564 | } |
567 | 565 | ||
@@ -590,21 +588,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
590 | } | 588 | } |
591 | } | 589 | } |
592 | 590 | ||
593 | protected void ReceivedAllAssets( | 591 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut) |
594 | ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | ||
595 | { | 592 | { |
596 | foreach (UUID uuid in assetsNotFoundUuids) | 593 | string errorMessage; |
594 | |||
595 | if (timedOut) | ||
597 | { | 596 | { |
598 | m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); | 597 | errorMessage = "Loading assets timed out"; |
599 | } | 598 | } |
599 | else | ||
600 | { | ||
601 | foreach (UUID uuid in assetsNotFoundUuids) | ||
602 | { | ||
603 | m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); | ||
604 | } | ||
600 | 605 | ||
601 | // m_log.InfoFormat( | 606 | // m_log.InfoFormat( |
602 | // "[ARCHIVER]: Received {0} of {1} assets requested", | 607 | // "[ARCHIVER]: Received {0} of {1} assets requested", |
603 | // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); | 608 | // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); |
604 | 609 | ||
605 | CloseArchive(String.Empty); | 610 | errorMessage = String.Empty; |
611 | } | ||
612 | |||
613 | CloseArchive(errorMessage); | ||
606 | } | 614 | } |
607 | |||
608 | 615 | ||
609 | /// <summary> | 616 | /// <summary> |
610 | /// Closes the archive and notifies that we're done. | 617 | /// Closes the archive and notifies that we're done. |
@@ -629,6 +636,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
629 | 636 | ||
630 | m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); | 637 | m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); |
631 | } | 638 | } |
632 | |||
633 | } | 639 | } |
634 | } | 640 | } |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs index 95d109c..c1ff94d 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs | |||
@@ -150,12 +150,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
150 | m_log.InfoFormat("[ARCHIVER]: Added {0} assets to archive", m_assetsWritten); | 150 | m_log.InfoFormat("[ARCHIVER]: Added {0} assets to archive", m_assetsWritten); |
151 | } | 151 | } |
152 | 152 | ||
153 | /// <summary> | ||
154 | /// Only call this if you need to force a close on the underlying writer. | ||
155 | /// </summary> | ||
156 | public void ForceClose() | ||
157 | { | ||
158 | m_archiveWriter.Close(); | ||
159 | } | ||
160 | } | 153 | } |
161 | } | 154 | } |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index e2f8833..ada7ecc 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | |||
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
50 | /// Method called when all the necessary assets for an archive request have been received. | 50 | /// Method called when all the necessary assets for an archive request have been received. |
51 | /// </summary> | 51 | /// </summary> |
52 | public delegate void AssetsRequestCallback( | 52 | public delegate void AssetsRequestCallback( |
53 | ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids); | 53 | ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut); |
54 | 54 | ||
55 | enum RequestState | 55 | enum RequestState |
56 | { | 56 | { |
@@ -148,7 +148,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
148 | if (m_repliesRequired == 0) | 148 | if (m_repliesRequired == 0) |
149 | { | 149 | { |
150 | m_requestState = RequestState.Completed; | 150 | m_requestState = RequestState.Completed; |
151 | PerformAssetsRequestCallback(null); | 151 | PerformAssetsRequestCallback(false); |
152 | return; | 152 | return; |
153 | } | 153 | } |
154 | 154 | ||
@@ -156,6 +156,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
156 | 156 | ||
157 | foreach (KeyValuePair<UUID, AssetType> kvp in m_uuids) | 157 | foreach (KeyValuePair<UUID, AssetType> kvp in m_uuids) |
158 | { | 158 | { |
159 | // m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); | ||
160 | |||
159 | // m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); | 161 | // m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); |
160 | AssetBase asset = m_assetService.Get(kvp.Key.ToString()); | 162 | AssetBase asset = m_assetService.Get(kvp.Key.ToString()); |
161 | PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); | 163 | PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); |
@@ -164,7 +166,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
164 | 166 | ||
165 | protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) | 167 | protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) |
166 | { | 168 | { |
167 | bool close = true; | 169 | bool timedOut = true; |
168 | 170 | ||
169 | try | 171 | try |
170 | { | 172 | { |
@@ -174,7 +176,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
174 | // the final request came in (assuming that such a thing is possible) | 176 | // the final request came in (assuming that such a thing is possible) |
175 | if (m_requestState == RequestState.Completed) | 177 | if (m_requestState == RequestState.Completed) |
176 | { | 178 | { |
177 | close = false; | 179 | timedOut = false; |
178 | return; | 180 | return; |
179 | } | 181 | } |
180 | 182 | ||
@@ -223,8 +225,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
223 | } | 225 | } |
224 | finally | 226 | finally |
225 | { | 227 | { |
226 | if (close) | 228 | if (timedOut) |
227 | m_assetsArchiver.ForceClose(); | 229 | Util.FireAndForget(PerformAssetsRequestCallback, true); |
228 | } | 230 | } |
229 | } | 231 | } |
230 | 232 | ||
@@ -290,7 +292,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
290 | 292 | ||
291 | // We want to stop using the asset cache thread asap | 293 | // We want to stop using the asset cache thread asap |
292 | // as we now need to do the work of producing the rest of the archive | 294 | // as we now need to do the work of producing the rest of the archive |
293 | Util.FireAndForget(PerformAssetsRequestCallback); | 295 | Util.FireAndForget(PerformAssetsRequestCallback, false); |
294 | } | 296 | } |
295 | else | 297 | else |
296 | { | 298 | { |
@@ -311,9 +313,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
311 | { | 313 | { |
312 | Culture.SetCurrentCulture(); | 314 | Culture.SetCurrentCulture(); |
313 | 315 | ||
316 | Boolean timedOut = (Boolean)o; | ||
317 | |||
314 | try | 318 | try |
315 | { | 319 | { |
316 | m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids); | 320 | m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids, timedOut); |
317 | } | 321 | } |
318 | catch (Exception e) | 322 | catch (Exception e) |
319 | { | 323 | { |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 82f49b0..eec1cec 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | |||
@@ -31,16 +31,19 @@ using System.IO; | |||
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | 32 | using System.Threading; |
33 | using log4net.Config; | 33 | using log4net.Config; |
34 | using Nini.Config; | ||
34 | using NUnit.Framework; | 35 | using NUnit.Framework; |
35 | using OpenMetaverse; | 36 | using OpenMetaverse; |
36 | using OpenMetaverse.Assets; | 37 | using OpenMetaverse.Assets; |
37 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
38 | using OpenSim.Framework.Serialization; | 39 | using OpenSim.Framework.Serialization; |
39 | using OpenSim.Framework.Serialization.External; | 40 | using OpenSim.Framework.Serialization.External; |
41 | using OpenSim.Region.CoreModules.World.Land; | ||
40 | using OpenSim.Region.CoreModules.World.Serialiser; | 42 | using OpenSim.Region.CoreModules.World.Serialiser; |
41 | using OpenSim.Region.CoreModules.World.Terrain; | 43 | using OpenSim.Region.CoreModules.World.Terrain; |
42 | using OpenSim.Region.Framework.Scenes; | 44 | using OpenSim.Region.Framework.Scenes; |
43 | using OpenSim.Region.Framework.Scenes.Serialization; | 45 | using OpenSim.Region.Framework.Scenes.Serialization; |
46 | using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; | ||
44 | using OpenSim.Tests.Common; | 47 | using OpenSim.Tests.Common; |
45 | using OpenSim.Tests.Common.Mock; | 48 | using OpenSim.Tests.Common.Mock; |
46 | using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; | 49 | using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; |
@@ -69,9 +72,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
69 | { | 72 | { |
70 | base.SetUp(); | 73 | base.SetUp(); |
71 | 74 | ||
72 | // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later | ||
73 | new SceneManager(); | ||
74 | |||
75 | m_archiverModule = new ArchiverModule(); | 75 | m_archiverModule = new ArchiverModule(); |
76 | m_serialiserModule = new SerialiserModule(); | 76 | m_serialiserModule = new SerialiserModule(); |
77 | TerrainModule terrainModule = new TerrainModule(); | 77 | TerrainModule terrainModule = new TerrainModule(); |
@@ -127,6 +127,53 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
127 | 127 | ||
128 | return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; | 128 | return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; |
129 | } | 129 | } |
130 | |||
131 | private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) | ||
132 | { | ||
133 | SceneObjectPart part1 = CreateSceneObjectPart1(); | ||
134 | sog1 = new SceneObjectGroup(part1); | ||
135 | scene.AddNewSceneObject(sog1, false); | ||
136 | |||
137 | AssetNotecard nc = new AssetNotecard(); | ||
138 | nc.BodyText = "Hello World!"; | ||
139 | nc.Encode(); | ||
140 | ncAssetUuid = UUID.Random(); | ||
141 | UUID ncItemUuid = UUID.Random(); | ||
142 | AssetBase ncAsset | ||
143 | = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); | ||
144 | m_scene.AssetService.Store(ncAsset); | ||
145 | |||
146 | TaskInventoryItem ncItem | ||
147 | = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; | ||
148 | SceneObjectPart part2 = CreateSceneObjectPart2(); | ||
149 | sog2 = new SceneObjectGroup(part2); | ||
150 | part2.Inventory.AddInventoryItem(ncItem, true); | ||
151 | |||
152 | scene.AddNewSceneObject(sog2, false); | ||
153 | } | ||
154 | |||
155 | private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) | ||
156 | { | ||
157 | using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) | ||
158 | { | ||
159 | using (BinaryReader br = new BinaryReader(resource)) | ||
160 | { | ||
161 | // FIXME: Use the inspector instead | ||
162 | soundData = br.ReadBytes(99999999); | ||
163 | soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); | ||
164 | string soundAssetFileName | ||
165 | = ArchiveConstants.ASSETS_PATH + soundUuid | ||
166 | + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; | ||
167 | tar.WriteFile(soundAssetFileName, soundData); | ||
168 | |||
169 | /* | ||
170 | AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); | ||
171 | scene.AssetService.Store(soundAsset); | ||
172 | asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; | ||
173 | */ | ||
174 | } | ||
175 | } | ||
176 | } | ||
130 | 177 | ||
131 | /// <summary> | 178 | /// <summary> |
132 | /// Test saving an OpenSim Region Archive. | 179 | /// Test saving an OpenSim Region Archive. |
@@ -204,30 +251,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
204 | // TODO: Test presence of more files and contents of files. | 251 | // TODO: Test presence of more files and contents of files. |
205 | } | 252 | } |
206 | 253 | ||
207 | private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) | ||
208 | { | ||
209 | SceneObjectPart part1 = CreateSceneObjectPart1(); | ||
210 | sog1 = new SceneObjectGroup(part1); | ||
211 | scene.AddNewSceneObject(sog1, false); | ||
212 | |||
213 | AssetNotecard nc = new AssetNotecard(); | ||
214 | nc.BodyText = "Hello World!"; | ||
215 | nc.Encode(); | ||
216 | ncAssetUuid = UUID.Random(); | ||
217 | UUID ncItemUuid = UUID.Random(); | ||
218 | AssetBase ncAsset | ||
219 | = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); | ||
220 | m_scene.AssetService.Store(ncAsset); | ||
221 | |||
222 | TaskInventoryItem ncItem | ||
223 | = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; | ||
224 | SceneObjectPart part2 = CreateSceneObjectPart2(); | ||
225 | sog2 = new SceneObjectGroup(part2); | ||
226 | part2.Inventory.AddInventoryItem(ncItem, true); | ||
227 | |||
228 | scene.AddNewSceneObject(sog2, false); | ||
229 | } | ||
230 | |||
231 | /// <summary> | 254 | /// <summary> |
232 | /// Test saving an OpenSim Region Archive with the no assets option | 255 | /// Test saving an OpenSim Region Archive with the no assets option |
233 | /// </summary> | 256 | /// </summary> |
@@ -309,59 +332,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
309 | } | 332 | } |
310 | 333 | ||
311 | /// <summary> | 334 | /// <summary> |
312 | /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g. | ||
313 | /// 2 can come after 3). | ||
314 | /// </summary> | ||
315 | [Test] | ||
316 | public void TestLoadOarUnorderedParts() | ||
317 | { | ||
318 | TestHelpers.InMethod(); | ||
319 | |||
320 | UUID ownerId = TestHelpers.ParseTail(0xaaaa); | ||
321 | |||
322 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
323 | TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); | ||
324 | |||
325 | tar.WriteFile( | ||
326 | ArchiveConstants.CONTROL_FILE_PATH, | ||
327 | new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); | ||
328 | |||
329 | SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); | ||
330 | SceneObjectPart sop2 | ||
331 | = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId); | ||
332 | SceneObjectPart sop3 | ||
333 | = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId); | ||
334 | |||
335 | // Add the parts so they will be written out in reverse order to the oar | ||
336 | sog1.AddPart(sop3); | ||
337 | sop3.LinkNum = 3; | ||
338 | sog1.AddPart(sop2); | ||
339 | sop2.LinkNum = 2; | ||
340 | |||
341 | tar.WriteFile( | ||
342 | ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition), | ||
343 | SceneObjectSerializer.ToXml2Format(sog1)); | ||
344 | |||
345 | tar.Close(); | ||
346 | |||
347 | MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); | ||
348 | |||
349 | lock (this) | ||
350 | { | ||
351 | m_scene.EventManager.OnOarFileLoaded += LoadCompleted; | ||
352 | m_archiverModule.DearchiveRegion(archiveReadStream); | ||
353 | } | ||
354 | |||
355 | Assert.That(m_lastErrorMessage, Is.Null); | ||
356 | |||
357 | SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2"); | ||
358 | Assert.That(part2.LinkNum, Is.EqualTo(2)); | ||
359 | |||
360 | SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3"); | ||
361 | Assert.That(part3.LinkNum, Is.EqualTo(3)); | ||
362 | } | ||
363 | |||
364 | /// <summary> | ||
365 | /// Test loading an OpenSim Region Archive. | 335 | /// Test loading an OpenSim Region Archive. |
366 | /// </summary> | 336 | /// </summary> |
367 | [Test] | 337 | [Test] |
@@ -435,50 +405,57 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
435 | TestLoadedRegion(part1, soundItemName, soundData); | 405 | TestLoadedRegion(part1, soundItemName, soundData); |
436 | } | 406 | } |
437 | 407 | ||
438 | private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) | 408 | /// <summary> |
409 | /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g. | ||
410 | /// 2 can come after 3). | ||
411 | /// </summary> | ||
412 | [Test] | ||
413 | public void TestLoadOarUnorderedParts() | ||
439 | { | 414 | { |
440 | using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) | 415 | TestHelpers.InMethod(); |
441 | { | ||
442 | using (BinaryReader br = new BinaryReader(resource)) | ||
443 | { | ||
444 | // FIXME: Use the inspector instead | ||
445 | soundData = br.ReadBytes(99999999); | ||
446 | soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); | ||
447 | string soundAssetFileName | ||
448 | = ArchiveConstants.ASSETS_PATH + soundUuid | ||
449 | + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; | ||
450 | tar.WriteFile(soundAssetFileName, soundData); | ||
451 | 416 | ||
452 | /* | 417 | UUID ownerId = TestHelpers.ParseTail(0xaaaa); |
453 | AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); | ||
454 | scene.AssetService.Store(soundAsset); | ||
455 | asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; | ||
456 | */ | ||
457 | } | ||
458 | } | ||
459 | } | ||
460 | 418 | ||
461 | private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) | 419 | MemoryStream archiveWriteStream = new MemoryStream(); |
462 | { | 420 | TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); |
463 | SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); | ||
464 | 421 | ||
465 | Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); | 422 | tar.WriteFile( |
466 | Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); | 423 | ArchiveConstants.CONTROL_FILE_PATH, |
467 | Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); | 424 | new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); |
468 | Assert.That( | ||
469 | object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); | ||
470 | Assert.That( | ||
471 | object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); | ||
472 | Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); | ||
473 | Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition)); | ||
474 | 425 | ||
475 | TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; | 426 | SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); |
476 | Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); | 427 | SceneObjectPart sop2 |
477 | AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); | 428 | = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId); |
478 | Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); | 429 | SceneObjectPart sop3 |
479 | Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); | 430 | = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId); |
480 | 431 | ||
481 | Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); | 432 | // Add the parts so they will be written out in reverse order to the oar |
433 | sog1.AddPart(sop3); | ||
434 | sop3.LinkNum = 3; | ||
435 | sog1.AddPart(sop2); | ||
436 | sop2.LinkNum = 2; | ||
437 | |||
438 | tar.WriteFile( | ||
439 | ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition), | ||
440 | SceneObjectSerializer.ToXml2Format(sog1)); | ||
441 | |||
442 | tar.Close(); | ||
443 | |||
444 | MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); | ||
445 | |||
446 | lock (this) | ||
447 | { | ||
448 | m_scene.EventManager.OnOarFileLoaded += LoadCompleted; | ||
449 | m_archiverModule.DearchiveRegion(archiveReadStream); | ||
450 | } | ||
451 | |||
452 | Assert.That(m_lastErrorMessage, Is.Null); | ||
453 | |||
454 | SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2"); | ||
455 | Assert.That(part2.LinkNum, Is.EqualTo(2)); | ||
456 | |||
457 | SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3"); | ||
458 | Assert.That(part3.LinkNum, Is.EqualTo(3)); | ||
482 | } | 459 | } |
483 | 460 | ||
484 | /// <summary> | 461 | /// <summary> |
@@ -538,8 +515,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
538 | SerialiserModule serialiserModule = new SerialiserModule(); | 515 | SerialiserModule serialiserModule = new SerialiserModule(); |
539 | TerrainModule terrainModule = new TerrainModule(); | 516 | TerrainModule terrainModule = new TerrainModule(); |
540 | 517 | ||
541 | m_sceneHelpers = new SceneHelpers(); | 518 | SceneHelpers m_sceneHelpers2 = new SceneHelpers(); |
542 | TestScene scene2 = m_sceneHelpers.SetupScene(); | 519 | TestScene scene2 = m_sceneHelpers2.SetupScene(); |
543 | SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); | 520 | SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); |
544 | 521 | ||
545 | // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is | 522 | // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is |
@@ -563,6 +540,71 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
563 | } | 540 | } |
564 | 541 | ||
565 | /// <summary> | 542 | /// <summary> |
543 | /// Test OAR loading where the land parcel is group deeded. | ||
544 | /// </summary> | ||
545 | /// <remarks> | ||
546 | /// In this situation, the owner ID is set to the group ID. | ||
547 | /// </remarks> | ||
548 | [Test] | ||
549 | public void TestLoadOarDeededLand() | ||
550 | { | ||
551 | TestHelpers.InMethod(); | ||
552 | // TestHelpers.EnableLogging(); | ||
553 | |||
554 | UUID landID = TestHelpers.ParseTail(0x10); | ||
555 | |||
556 | MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector(); | ||
557 | |||
558 | IConfigSource configSource = new IniConfigSource(); | ||
559 | IConfig config = configSource.AddConfig("Groups"); | ||
560 | config.Set("Enabled", true); | ||
561 | config.Set("Module", "GroupsModule"); | ||
562 | config.Set("DebugEnabled", true); | ||
563 | SceneHelpers.SetupSceneModules( | ||
564 | m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() }); | ||
565 | |||
566 | // Create group in scene for loading | ||
567 | // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests. | ||
568 | UUID groupID | ||
569 | = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero); | ||
570 | |||
571 | // Construct OAR | ||
572 | MemoryStream oarStream = new MemoryStream(); | ||
573 | TarArchiveWriter tar = new TarArchiveWriter(oarStream); | ||
574 | |||
575 | tar.WriteDir(ArchiveConstants.LANDDATA_PATH); | ||
576 | tar.WriteFile( | ||
577 | ArchiveConstants.CONTROL_FILE_PATH, | ||
578 | new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); | ||
579 | |||
580 | LandObject lo = new LandObject(groupID, true, null); | ||
581 | lo.SetLandBitmap(lo.BasicFullRegionLandBitmap()); | ||
582 | LandData ld = lo.LandData; | ||
583 | ld.GlobalID = landID; | ||
584 | |||
585 | string ldPath = ArchiveConstants.CreateOarLandDataPath(ld); | ||
586 | tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, null)); | ||
587 | tar.Close(); | ||
588 | |||
589 | oarStream = new MemoryStream(oarStream.ToArray()); | ||
590 | |||
591 | // Load OAR | ||
592 | lock (this) | ||
593 | { | ||
594 | m_scene.EventManager.OnOarFileLoaded += LoadCompleted; | ||
595 | m_archiverModule.DearchiveRegion(oarStream); | ||
596 | } | ||
597 | |||
598 | ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16); | ||
599 | LandData rLd = rLo.LandData; | ||
600 | |||
601 | Assert.That(rLd.GlobalID, Is.EqualTo(landID)); | ||
602 | Assert.That(rLd.OwnerID, Is.EqualTo(groupID)); | ||
603 | Assert.That(rLd.GroupID, Is.EqualTo(groupID)); | ||
604 | Assert.That(rLd.IsGroupOwned, Is.EqualTo(true)); | ||
605 | } | ||
606 | |||
607 | /// <summary> | ||
566 | /// Test loading the region settings of an OpenSim Region Archive. | 608 | /// Test loading the region settings of an OpenSim Region Archive. |
567 | /// </summary> | 609 | /// </summary> |
568 | [Test] | 610 | [Test] |
@@ -781,9 +823,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
781 | } | 823 | } |
782 | } | 824 | } |
783 | 825 | ||
784 | |||
785 | // Save OAR | 826 | // Save OAR |
786 | |||
787 | MemoryStream archiveWriteStream = new MemoryStream(); | 827 | MemoryStream archiveWriteStream = new MemoryStream(); |
788 | m_scene.EventManager.OnOarFileSaved += SaveCompleted; | 828 | m_scene.EventManager.OnOarFileSaved += SaveCompleted; |
789 | 829 | ||
@@ -800,7 +840,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
800 | 840 | ||
801 | 841 | ||
802 | // Check that the OAR contains the expected data | 842 | // Check that the OAR contains the expected data |
803 | |||
804 | Assert.That(m_lastRequestId, Is.EqualTo(requestId)); | 843 | Assert.That(m_lastRequestId, Is.EqualTo(requestId)); |
805 | 844 | ||
806 | byte[] archive = archiveWriteStream.ToArray(); | 845 | byte[] archive = archiveWriteStream.ToArray(); |
@@ -892,7 +931,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
892 | } | 931 | } |
893 | 932 | ||
894 | ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); | 933 | ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); |
895 | SceneManager.Instance.ForEachScene(delegate(Scene scene) | 934 | m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene) |
896 | { | 935 | { |
897 | scenesGroup.AddScene(scene); | 936 | scenesGroup.AddScene(scene); |
898 | }); | 937 | }); |
@@ -950,13 +989,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
950 | 989 | ||
951 | // Delete the current objects, to test that they're loaded from the OAR and didn't | 990 | // Delete the current objects, to test that they're loaded from the OAR and didn't |
952 | // just remain in the scene. | 991 | // just remain in the scene. |
953 | SceneManager.Instance.ForEachScene(delegate(Scene scene) | 992 | m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene) |
954 | { | 993 | { |
955 | scene.DeleteAllSceneObjects(); | 994 | scene.DeleteAllSceneObjects(); |
956 | }); | 995 | }); |
957 | 996 | ||
958 | // Create a "hole", to test that that the corresponding region isn't loaded from the OAR | 997 | // Create a "hole", to test that that the corresponding region isn't loaded from the OAR |
959 | SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); | 998 | m_sceneHelpers.SceneManager.CloseScene(SceneManager.Instance.Scenes[1]); |
960 | 999 | ||
961 | 1000 | ||
962 | // Check thay the OAR file contains the expected data | 1001 | // Check thay the OAR file contains the expected data |
@@ -971,10 +1010,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
971 | 1010 | ||
972 | Assert.That(m_lastErrorMessage, Is.Null); | 1011 | Assert.That(m_lastErrorMessage, Is.Null); |
973 | 1012 | ||
974 | Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); | 1013 | Assert.AreEqual(3, m_sceneHelpers.SceneManager.Scenes.Count); |
975 | 1014 | ||
976 | TestLoadedRegion(part1, soundItemName, soundData); | 1015 | TestLoadedRegion(part1, soundItemName, soundData); |
977 | } | 1016 | } |
978 | 1017 | ||
1018 | private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) | ||
1019 | { | ||
1020 | SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); | ||
1021 | |||
1022 | Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); | ||
1023 | Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); | ||
1024 | Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); | ||
1025 | Assert.That( | ||
1026 | object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); | ||
1027 | Assert.That( | ||
1028 | object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); | ||
1029 | Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); | ||
1030 | Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition)); | ||
1031 | |||
1032 | TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; | ||
1033 | Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); | ||
1034 | AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); | ||
1035 | Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); | ||
1036 | Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); | ||
1037 | |||
1038 | Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); | ||
1039 | } | ||
979 | } | 1040 | } |
980 | } | 1041 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs index 3b84d57..4d49794 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs | |||
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
117 | 117 | ||
118 | m_module.Scene.RegionInfo.RegionSettings.Save(); | 118 | m_module.Scene.RegionInfo.RegionSettings.Save(); |
119 | m_module.TriggerRegionInfoChange(); | 119 | m_module.TriggerRegionInfoChange(); |
120 | m_module.sendRegionInfoPacketToAll(); | 120 | m_module.sendRegionHandshakeToAll(); |
121 | } | 121 | } |
122 | } | 122 | } |
123 | } | 123 | } |
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index dc062b6..a5f5749 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | |||
@@ -55,6 +55,11 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
55 | 55 | ||
56 | protected EstateManagementCommands m_commands; | 56 | protected EstateManagementCommands m_commands; |
57 | 57 | ||
58 | /// <summary> | ||
59 | /// If false, region restart requests from the client are blocked even if they are otherwise legitimate. | ||
60 | /// </summary> | ||
61 | public bool AllowRegionRestartFromClient { get; set; } | ||
62 | |||
58 | private EstateTerrainXferHandler TerrainUploader; | 63 | private EstateTerrainXferHandler TerrainUploader; |
59 | public TelehubManager m_Telehub; | 64 | public TelehubManager m_Telehub; |
60 | 65 | ||
@@ -64,6 +69,53 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
64 | 69 | ||
65 | private int m_delayCount = 0; | 70 | private int m_delayCount = 0; |
66 | 71 | ||
72 | #region Region Module interface | ||
73 | |||
74 | public string Name { get { return "EstateManagementModule"; } } | ||
75 | |||
76 | public Type ReplaceableInterface { get { return null; } } | ||
77 | |||
78 | public void Initialise(IConfigSource source) | ||
79 | { | ||
80 | AllowRegionRestartFromClient = true; | ||
81 | |||
82 | IConfig config = source.Configs["EstateManagement"]; | ||
83 | |||
84 | if (config != null) | ||
85 | AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true); | ||
86 | } | ||
87 | |||
88 | public void AddRegion(Scene scene) | ||
89 | { | ||
90 | Scene = scene; | ||
91 | Scene.RegisterModuleInterface<IEstateModule>(this); | ||
92 | Scene.EventManager.OnNewClient += EventManager_OnNewClient; | ||
93 | Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight; | ||
94 | |||
95 | m_Telehub = new TelehubManager(scene); | ||
96 | |||
97 | m_commands = new EstateManagementCommands(this); | ||
98 | m_commands.Initialise(); | ||
99 | } | ||
100 | |||
101 | public void RemoveRegion(Scene scene) {} | ||
102 | |||
103 | public void RegionLoaded(Scene scene) | ||
104 | { | ||
105 | // Sets up the sun module based no the saved Estate and Region Settings | ||
106 | // DO NOT REMOVE or the sun will stop working | ||
107 | scene.TriggerEstateSunUpdate(); | ||
108 | |||
109 | UserManager = scene.RequestModuleInterface<IUserManagement>(); | ||
110 | } | ||
111 | |||
112 | public void Close() | ||
113 | { | ||
114 | m_commands.Close(); | ||
115 | } | ||
116 | |||
117 | #endregion | ||
118 | |||
67 | #region Packet Data Responders | 119 | #region Packet Data Responders |
68 | 120 | ||
69 | private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice) | 121 | private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice) |
@@ -76,7 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
76 | { | 128 | { |
77 | uint sun = 0; | 129 | uint sun = 0; |
78 | 130 | ||
79 | if (!Scene.RegionInfo.EstateSettings.UseGlobalTime) | 131 | if (Scene.RegionInfo.EstateSettings.FixedSun) |
80 | sun = (uint)(Scene.RegionInfo.EstateSettings.SunPosition * 1024.0) + 0x1800; | 132 | sun = (uint)(Scene.RegionInfo.EstateSettings.SunPosition * 1024.0) + 0x1800; |
81 | UUID estateOwner; | 133 | UUID estateOwner; |
82 | estateOwner = Scene.RegionInfo.EstateSettings.EstateOwner; | 134 | estateOwner = Scene.RegionInfo.EstateSettings.EstateOwner; |
@@ -197,6 +249,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
197 | Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; | 249 | Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; |
198 | break; | 250 | break; |
199 | } | 251 | } |
252 | |||
200 | Scene.RegionInfo.RegionSettings.Save(); | 253 | Scene.RegionInfo.RegionSettings.Save(); |
201 | TriggerRegionInfoChange(); | 254 | TriggerRegionInfoChange(); |
202 | sendRegionInfoPacketToAll(); | 255 | sendRegionInfoPacketToAll(); |
@@ -228,6 +281,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
228 | Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; | 281 | Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; |
229 | break; | 282 | break; |
230 | } | 283 | } |
284 | |||
231 | Scene.RegionInfo.RegionSettings.Save(); | 285 | Scene.RegionInfo.RegionSettings.Save(); |
232 | TriggerRegionInfoChange(); | 286 | TriggerRegionInfoChange(); |
233 | sendRegionHandshakeToAll(); | 287 | sendRegionHandshakeToAll(); |
@@ -268,6 +322,12 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
268 | 322 | ||
269 | private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) | 323 | private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) |
270 | { | 324 | { |
325 | if (!AllowRegionRestartFromClient) | ||
326 | { | ||
327 | remoteClient.SendAlertMessage("Region restart has been disabled on this simulator."); | ||
328 | return; | ||
329 | } | ||
330 | |||
271 | IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); | 331 | IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); |
272 | if (restartModule != null) | 332 | if (restartModule != null) |
273 | { | 333 | { |
@@ -352,6 +412,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
352 | } | 412 | } |
353 | 413 | ||
354 | } | 414 | } |
415 | |||
355 | if ((estateAccessType & 8) != 0) // User remove | 416 | if ((estateAccessType & 8) != 0) // User remove |
356 | { | 417 | { |
357 | if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) | 418 | if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) |
@@ -383,6 +444,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
383 | remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); | 444 | remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); |
384 | } | 445 | } |
385 | } | 446 | } |
447 | |||
386 | if ((estateAccessType & 16) != 0) // Group add | 448 | if ((estateAccessType & 16) != 0) // Group add |
387 | { | 449 | { |
388 | if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) | 450 | if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) |
@@ -650,7 +712,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
650 | } | 712 | } |
651 | } | 713 | } |
652 | 714 | ||
653 | public void handleOnEstateManageTelehub (IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) | 715 | public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) |
654 | { | 716 | { |
655 | SceneObjectPart part; | 717 | SceneObjectPart part; |
656 | 718 | ||
@@ -718,13 +780,18 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
718 | Scene.RegionInfo.RegionSettings.Save(); | 780 | Scene.RegionInfo.RegionSettings.Save(); |
719 | TriggerRegionInfoChange(); | 781 | TriggerRegionInfoChange(); |
720 | 782 | ||
721 | Scene.SetSceneCoreDebug( | 783 | ISceneCommandsModule scm = Scene.RequestModuleInterface<ISceneCommandsModule>(); |
722 | new Dictionary<string, string>() { | 784 | |
723 | { "scripting", (!disableScripts).ToString() }, | 785 | if (scm != null) |
724 | { "collisions", (!disableCollisions).ToString() }, | 786 | { |
725 | { "physics", (!disablePhysics).ToString() } | 787 | scm.SetSceneDebugOptions( |
726 | } | 788 | new Dictionary<string, string>() { |
727 | ); | 789 | { "scripting", (!disableScripts).ToString() }, |
790 | { "collisions", (!disableCollisions).ToString() }, | ||
791 | { "physics", (!disablePhysics).ToString() } | ||
792 | } | ||
793 | ); | ||
794 | } | ||
728 | } | 795 | } |
729 | 796 | ||
730 | private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) | 797 | private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) |
@@ -1066,6 +1133,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
1066 | { | 1133 | { |
1067 | Scene.RegionInfo.EstateSettings.UseGlobalTime = false; | 1134 | Scene.RegionInfo.EstateSettings.UseGlobalTime = false; |
1068 | Scene.RegionInfo.EstateSettings.SunPosition = (parms2 - 0x1800)/1024.0; | 1135 | Scene.RegionInfo.EstateSettings.SunPosition = (parms2 - 0x1800)/1024.0; |
1136 | // Warning: FixedSun should be set to True, otherwise this sun position won't be used. | ||
1069 | } | 1137 | } |
1070 | 1138 | ||
1071 | if ((parms1 & 0x00000010) != 0) | 1139 | if ((parms1 & 0x00000010) != 0) |
@@ -1118,49 +1186,6 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
1118 | 1186 | ||
1119 | #endregion | 1187 | #endregion |
1120 | 1188 | ||
1121 | #region Region Module interface | ||
1122 | |||
1123 | public string Name { get { return "EstateManagementModule"; } } | ||
1124 | |||
1125 | public Type ReplaceableInterface { get { return null; } } | ||
1126 | |||
1127 | public void Initialise(IConfigSource source) {} | ||
1128 | |||
1129 | public void AddRegion(Scene scene) | ||
1130 | { | ||
1131 | m_regionChangeTimer.AutoReset = false; | ||
1132 | m_regionChangeTimer.Interval = 2000; | ||
1133 | m_regionChangeTimer.Elapsed += RaiseRegionInfoChange; | ||
1134 | |||
1135 | Scene = scene; | ||
1136 | Scene.RegisterModuleInterface<IEstateModule>(this); | ||
1137 | Scene.EventManager.OnNewClient += EventManager_OnNewClient; | ||
1138 | Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight; | ||
1139 | |||
1140 | m_Telehub = new TelehubManager(scene); | ||
1141 | |||
1142 | m_commands = new EstateManagementCommands(this); | ||
1143 | m_commands.Initialise(); | ||
1144 | } | ||
1145 | |||
1146 | public void RemoveRegion(Scene scene) {} | ||
1147 | |||
1148 | public void RegionLoaded(Scene scene) | ||
1149 | { | ||
1150 | // Sets up the sun module based no the saved Estate and Region Settings | ||
1151 | // DO NOT REMOVE or the sun will stop working | ||
1152 | scene.TriggerEstateSunUpdate(); | ||
1153 | |||
1154 | UserManager = scene.RequestModuleInterface<IUserManagement>(); | ||
1155 | } | ||
1156 | |||
1157 | public void Close() | ||
1158 | { | ||
1159 | m_commands.Close(); | ||
1160 | } | ||
1161 | |||
1162 | #endregion | ||
1163 | |||
1164 | #region Other Functions | 1189 | #region Other Functions |
1165 | 1190 | ||
1166 | public void changeWaterHeight(float height) | 1191 | public void changeWaterHeight(float height) |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs index 7fc358d..73c592d 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs | |||
@@ -95,6 +95,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
95 | return null; | 95 | return null; |
96 | } | 96 | } |
97 | 97 | ||
98 | public ILandObject GetLandObject(Vector3 position) | ||
99 | { | ||
100 | return GetLandObject(position.X, position.Y); | ||
101 | } | ||
102 | |||
98 | public ILandObject GetLandObject(int x, int y) | 103 | public ILandObject GetLandObject(int x, int y) |
99 | { | 104 | { |
100 | if (m_landManagementModule != null) | 105 | if (m_landManagementModule != null) |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 1193057..b4f7d51 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | |||
@@ -141,6 +141,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
141 | m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy; | 141 | m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy; |
142 | m_scene.EventManager.OnLandBuy += EventManagerOnLandBuy; | 142 | m_scene.EventManager.OnLandBuy += EventManagerOnLandBuy; |
143 | m_scene.EventManager.OnNewClient += EventManagerOnNewClient; | 143 | m_scene.EventManager.OnNewClient += EventManagerOnNewClient; |
144 | m_scene.EventManager.OnMakeChildAgent += EventMakeChildAgent; | ||
144 | m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement; | 145 | m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement; |
145 | m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage; | 146 | m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage; |
146 | m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; | 147 | m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; |
@@ -221,6 +222,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
221 | } | 222 | } |
222 | } | 223 | } |
223 | 224 | ||
225 | public void EventMakeChildAgent(ScenePresence avatar) | ||
226 | { | ||
227 | avatar.currentParcelUUID = UUID.Zero; | ||
228 | } | ||
229 | |||
224 | void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | 230 | void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) |
225 | { | 231 | { |
226 | } | 232 | } |
@@ -249,17 +255,15 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
249 | newData.LocalID = local_id; | 255 | newData.LocalID = local_id; |
250 | ILandObject landobj = null; | 256 | ILandObject landobj = null; |
251 | 257 | ||
258 | ILandObject land; | ||
252 | lock (m_landList) | 259 | lock (m_landList) |
253 | { | 260 | { |
254 | if (m_landList.ContainsKey(local_id)) | 261 | if (m_landList.TryGetValue(local_id, out land)) |
255 | { | 262 | land.LandData = newData; |
256 | m_landList[local_id].LandData = newData; | ||
257 | landobj = m_landList[local_id]; | ||
258 | // m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]); | ||
259 | } | ||
260 | } | 263 | } |
261 | if(landobj != null) | 264 | |
262 | m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, landobj); | 265 | if (land != null) |
266 | m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land); | ||
263 | } | 267 | } |
264 | 268 | ||
265 | public bool AllowedForcefulBans | 269 | public bool AllowedForcefulBans |
@@ -584,7 +588,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
584 | // Only now can we add the prim counts to the land object - we rely on the global ID which is generated | 588 | // Only now can we add the prim counts to the land object - we rely on the global ID which is generated |
585 | // as a random UUID inside LandData initialization | 589 | // as a random UUID inside LandData initialization |
586 | if (m_primCountModule != null) | 590 | if (m_primCountModule != null) |
587 | new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID); | 591 | new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID); |
588 | 592 | ||
589 | lock (m_landList) | 593 | lock (m_landList) |
590 | { | 594 | { |
@@ -621,6 +625,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
621 | /// <param name="local_id">Land.localID of the peice of land to remove.</param> | 625 | /// <param name="local_id">Land.localID of the peice of land to remove.</param> |
622 | public void removeLandObject(int local_id) | 626 | public void removeLandObject(int local_id) |
623 | { | 627 | { |
628 | ILandObject land; | ||
624 | lock (m_landList) | 629 | lock (m_landList) |
625 | { | 630 | { |
626 | for (int x = 0; x < 64; x++) | 631 | for (int x = 0; x < 64; x++) |
@@ -637,9 +642,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
637 | } | 642 | } |
638 | } | 643 | } |
639 | 644 | ||
640 | m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID); | 645 | land = m_landList[local_id]; |
641 | m_landList.Remove(local_id); | 646 | m_landList.Remove(local_id); |
642 | } | 647 | } |
648 | |||
649 | m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID); | ||
643 | } | 650 | } |
644 | 651 | ||
645 | /// <summary> | 652 | /// <summary> |
@@ -1384,9 +1391,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1384 | } | 1391 | } |
1385 | 1392 | ||
1386 | for (int i = 0; i < data.Count; i++) | 1393 | for (int i = 0; i < data.Count; i++) |
1387 | { | ||
1388 | IncomingLandObjectFromStorage(data[i]); | 1394 | IncomingLandObjectFromStorage(data[i]); |
1389 | } | ||
1390 | } | 1395 | } |
1391 | 1396 | ||
1392 | public void IncomingLandObjectFromStorage(LandData data) | 1397 | public void IncomingLandObjectFromStorage(LandData data) |
@@ -1401,25 +1406,72 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1401 | 1406 | ||
1402 | public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) | 1407 | public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) |
1403 | { | 1408 | { |
1404 | ILandObject selectedParcel = null; | 1409 | if (localID != -1) |
1405 | lock (m_landList) | ||
1406 | { | 1410 | { |
1407 | m_landList.TryGetValue(localID, out selectedParcel); | 1411 | ILandObject selectedParcel = null; |
1412 | lock (m_landList) | ||
1413 | { | ||
1414 | m_landList.TryGetValue(localID, out selectedParcel); | ||
1415 | } | ||
1416 | |||
1417 | if (selectedParcel == null) | ||
1418 | return; | ||
1419 | |||
1420 | selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); | ||
1408 | } | 1421 | } |
1422 | else | ||
1423 | { | ||
1424 | if (returnType != 1) | ||
1425 | { | ||
1426 | m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown return type {0}", returnType); | ||
1427 | return; | ||
1428 | } | ||
1429 | |||
1430 | // We get here when the user returns objects from the list of Top Colliders or Top Scripts. | ||
1431 | // In that case we receive specific object UUID's, but no parcel ID. | ||
1432 | |||
1433 | Dictionary<UUID, HashSet<SceneObjectGroup>> returns = new Dictionary<UUID, HashSet<SceneObjectGroup>>(); | ||
1434 | |||
1435 | foreach (UUID groupID in taskIDs) | ||
1436 | { | ||
1437 | SceneObjectGroup obj = m_scene.GetSceneObjectGroup(groupID); | ||
1438 | if (obj != null) | ||
1439 | { | ||
1440 | if (!returns.ContainsKey(obj.OwnerID)) | ||
1441 | returns[obj.OwnerID] = new HashSet<SceneObjectGroup>(); | ||
1442 | returns[obj.OwnerID].Add(obj); | ||
1443 | } | ||
1444 | else | ||
1445 | { | ||
1446 | m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: unknown object {0}", groupID); | ||
1447 | } | ||
1448 | } | ||
1409 | 1449 | ||
1410 | if (selectedParcel == null) return; | 1450 | int num = 0; |
1451 | foreach (HashSet<SceneObjectGroup> objs in returns.Values) | ||
1452 | num += objs.Count; | ||
1453 | m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Returning {0} specific object(s)", num); | ||
1411 | 1454 | ||
1412 | selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); | 1455 | foreach (HashSet<SceneObjectGroup> objs in returns.Values) |
1456 | { | ||
1457 | List<SceneObjectGroup> objs2 = new List<SceneObjectGroup>(objs); | ||
1458 | if (m_scene.Permissions.CanReturnObjects(null, remoteClient.AgentId, objs2)) | ||
1459 | { | ||
1460 | m_scene.returnObjects(objs2.ToArray(), remoteClient.AgentId); | ||
1461 | } | ||
1462 | else | ||
1463 | { | ||
1464 | m_log.WarnFormat("[LAND MANAGEMENT MODULE]: ReturnObjectsInParcel: not permitted to return {0} object(s) belonging to user {1}", | ||
1465 | objs2.Count, objs2[0].OwnerID); | ||
1466 | } | ||
1467 | } | ||
1468 | } | ||
1413 | } | 1469 | } |
1414 | 1470 | ||
1415 | public void EventManagerOnNoLandDataFromStorage() | 1471 | public void EventManagerOnNoLandDataFromStorage() |
1416 | { | 1472 | { |
1417 | // called methods already have locks | 1473 | ResetSimLandObjects(); |
1418 | // lock (m_landList) | 1474 | CreateDefaultParcel(); |
1419 | { | ||
1420 | ResetSimLandObjects(); | ||
1421 | CreateDefaultParcel(); | ||
1422 | } | ||
1423 | } | 1475 | } |
1424 | 1476 | ||
1425 | #endregion | 1477 | #endregion |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index fdac418..07d00c0 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs | |||
@@ -761,9 +761,10 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
761 | int ty = min_y * 4; | 761 | int ty = min_y * 4; |
762 | if (ty > ((int)Constants.RegionSize - 1)) | 762 | if (ty > ((int)Constants.RegionSize - 1)) |
763 | ty = ((int)Constants.RegionSize - 1); | 763 | ty = ((int)Constants.RegionSize - 1); |
764 | |||
764 | LandData.AABBMin = | 765 | LandData.AABBMin = |
765 | new Vector3((float) (min_x * 4), (float) (min_y * 4), | 766 | new Vector3( |
766 | (float) m_scene.Heightmap[tx, ty]); | 767 | (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); |
767 | 768 | ||
768 | tx = max_x * 4; | 769 | tx = max_x * 4; |
769 | if (tx > ((int)Constants.RegionSize - 1)) | 770 | if (tx > ((int)Constants.RegionSize - 1)) |
@@ -771,9 +772,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
771 | ty = max_y * 4; | 772 | ty = max_y * 4; |
772 | if (ty > ((int)Constants.RegionSize - 1)) | 773 | if (ty > ((int)Constants.RegionSize - 1)) |
773 | ty = ((int)Constants.RegionSize - 1); | 774 | ty = ((int)Constants.RegionSize - 1); |
774 | LandData.AABBMax = | 775 | |
775 | new Vector3((float) (max_x * 4), (float) (max_y * 4), | 776 | LandData.AABBMax |
776 | (float) m_scene.Heightmap[tx, ty]); | 777 | = new Vector3( |
778 | (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); | ||
779 | |||
777 | LandData.Area = tempArea; | 780 | LandData.Area = tempArea; |
778 | } | 781 | } |
779 | 782 | ||
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index 55b8227..771fdd2 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs | |||
@@ -490,11 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
490 | 490 | ||
491 | m_Scene.ForEachSOG(AddObject); | 491 | m_Scene.ForEachSOG(AddObject); |
492 | 492 | ||
493 | List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys); | 493 | lock (m_PrimCounts) |
494 | foreach (UUID k in primcountKeys) | ||
495 | { | 494 | { |
496 | if (!m_OwnerMap.ContainsKey(k)) | 495 | List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys); |
497 | m_PrimCounts.Remove(k); | 496 | foreach (UUID k in primcountKeys) |
497 | { | ||
498 | if (!m_OwnerMap.ContainsKey(k)) | ||
499 | m_PrimCounts.Remove(k); | ||
500 | } | ||
498 | } | 501 | } |
499 | 502 | ||
500 | m_Tainted = false; | 503 | m_Tainted = false; |
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs index b5ee4d2..0945b43 100644 --- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs +++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs | |||
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common.Mock; | |||
41 | namespace OpenSim.Region.CoreModules.World.Land.Tests | 41 | namespace OpenSim.Region.CoreModules.World.Land.Tests |
42 | { | 42 | { |
43 | [TestFixture] | 43 | [TestFixture] |
44 | public class PrimCountModuleTests | 44 | public class PrimCountModuleTests : OpenSimTestCase |
45 | { | 45 | { |
46 | protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); | 46 | protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); |
47 | protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); | 47 | protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); |
@@ -60,8 +60,10 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests | |||
60 | protected ILandObject m_lo2; | 60 | protected ILandObject m_lo2; |
61 | 61 | ||
62 | [SetUp] | 62 | [SetUp] |
63 | public void SetUp() | 63 | public override void SetUp() |
64 | { | 64 | { |
65 | base.SetUp(); | ||
66 | |||
65 | m_pcm = new PrimCountModule(); | 67 | m_pcm = new PrimCountModule(); |
66 | LandManagementModule lmm = new LandManagementModule(); | 68 | LandManagementModule lmm = new LandManagementModule(); |
67 | m_scene = new SceneHelpers().SetupScene(); | 69 | m_scene = new SceneHelpers().SetupScene(); |
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs index 8a422b0..40638f8 100644 --- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs | |||
@@ -77,42 +77,48 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
77 | { | 77 | { |
78 | bool drawPrimVolume = true; | 78 | bool drawPrimVolume = true; |
79 | bool textureTerrain = false; | 79 | bool textureTerrain = false; |
80 | bool generateMaptiles = true; | ||
81 | Bitmap mapbmp; | ||
80 | 82 | ||
81 | try | 83 | string[] configSections = new string[] { "Map", "Startup" }; |
82 | { | ||
83 | IConfig startupConfig = m_config.Configs["Startup"]; | ||
84 | drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume); | ||
85 | textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain); | ||
86 | } | ||
87 | catch | ||
88 | { | ||
89 | m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); | ||
90 | } | ||
91 | 84 | ||
92 | if (textureTerrain) | 85 | drawPrimVolume |
93 | { | 86 | = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume); |
94 | terrainRenderer = new TexturedMapTileRenderer(); | 87 | textureTerrain |
95 | } | 88 | = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain); |
96 | else | 89 | generateMaptiles |
90 | = Util.GetConfigVarFromSections<bool>(m_config, "GenerateMaptiles", configSections, generateMaptiles); | ||
91 | |||
92 | if (generateMaptiles) | ||
97 | { | 93 | { |
98 | terrainRenderer = new ShadedMapTileRenderer(); | 94 | if (textureTerrain) |
99 | } | 95 | { |
100 | terrainRenderer.Initialise(m_scene, m_config); | 96 | terrainRenderer = new TexturedMapTileRenderer(); |
97 | } | ||
98 | else | ||
99 | { | ||
100 | terrainRenderer = new ShadedMapTileRenderer(); | ||
101 | } | ||
101 | 102 | ||
102 | Bitmap mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb); | 103 | terrainRenderer.Initialise(m_scene, m_config); |
103 | //long t = System.Environment.TickCount; | ||
104 | //for (int i = 0; i < 10; ++i) { | ||
105 | terrainRenderer.TerrainToBitmap(mapbmp); | ||
106 | //} | ||
107 | //t = System.Environment.TickCount - t; | ||
108 | //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); | ||
109 | 104 | ||
105 | mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb); | ||
106 | //long t = System.Environment.TickCount; | ||
107 | //for (int i = 0; i < 10; ++i) { | ||
108 | terrainRenderer.TerrainToBitmap(mapbmp); | ||
109 | //} | ||
110 | //t = System.Environment.TickCount - t; | ||
111 | //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); | ||
110 | 112 | ||
111 | if (drawPrimVolume) | 113 | if (drawPrimVolume) |
114 | { | ||
115 | DrawObjectVolume(m_scene, mapbmp); | ||
116 | } | ||
117 | } | ||
118 | else | ||
112 | { | 119 | { |
113 | DrawObjectVolume(m_scene, mapbmp); | 120 | mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); |
114 | } | 121 | } |
115 | |||
116 | return mapbmp; | 122 | return mapbmp; |
117 | } | 123 | } |
118 | 124 | ||
@@ -139,9 +145,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
139 | { | 145 | { |
140 | m_config = source; | 146 | m_config = source; |
141 | 147 | ||
142 | IConfig startupConfig = m_config.Configs["Startup"]; | 148 | if (Util.GetConfigVarFromSections<string>( |
143 | if (startupConfig.GetString("MapImageModule", "MapImageModule") != | 149 | m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "MapImageModule") |
144 | "MapImageModule") | ||
145 | return; | 150 | return; |
146 | 151 | ||
147 | m_Enabled = true; | 152 | m_Enabled = true; |
@@ -222,6 +227,49 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
222 | // } | 227 | // } |
223 | // } | 228 | // } |
224 | 229 | ||
230 | private Bitmap FetchTexture(UUID id) | ||
231 | { | ||
232 | AssetBase asset = m_scene.AssetService.Get(id.ToString()); | ||
233 | |||
234 | if (asset != null) | ||
235 | { | ||
236 | m_log.DebugFormat("[MAPTILE]: Static map image texture {0} found for {1}", id, m_scene.Name); | ||
237 | } | ||
238 | else | ||
239 | { | ||
240 | m_log.WarnFormat("[MAPTILE]: Static map image texture {0} not found for {1}", id, m_scene.Name); | ||
241 | return null; | ||
242 | } | ||
243 | |||
244 | ManagedImage managedImage; | ||
245 | Image image; | ||
246 | |||
247 | try | ||
248 | { | ||
249 | if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image)) | ||
250 | return new Bitmap(image); | ||
251 | else | ||
252 | return null; | ||
253 | } | ||
254 | catch (DllNotFoundException) | ||
255 | { | ||
256 | m_log.ErrorFormat("[MAPTILE]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id); | ||
257 | |||
258 | } | ||
259 | catch (IndexOutOfRangeException) | ||
260 | { | ||
261 | m_log.ErrorFormat("[MAPTILE]: OpenJpeg was unable to decode this. Asset Data is empty for {0}", id); | ||
262 | |||
263 | } | ||
264 | catch (Exception) | ||
265 | { | ||
266 | m_log.ErrorFormat("[MAPTILE]: OpenJpeg was unable to decode this. Asset Data is empty for {0}", id); | ||
267 | |||
268 | } | ||
269 | return null; | ||
270 | |||
271 | } | ||
272 | |||
225 | private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp) | 273 | private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp) |
226 | { | 274 | { |
227 | int tc = 0; | 275 | int tc = 0; |
diff --git a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs index 6f92ef6..f13d648 100644 --- a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs +++ b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs | |||
@@ -198,12 +198,12 @@ namespace OpenSim.Region.CoreModules.World.LightShare | |||
198 | if (m_scene.RegionInfo.WindlightSettings.valid) | 198 | if (m_scene.RegionInfo.WindlightSettings.valid) |
199 | { | 199 | { |
200 | List<byte[]> param = compileWindlightSettings(wl); | 200 | List<byte[]> param = compileWindlightSettings(wl); |
201 | client.SendGenericMessage("Windlight", param); | 201 | client.SendGenericMessage("Windlight", UUID.Random(), param); |
202 | } | 202 | } |
203 | else | 203 | else |
204 | { | 204 | { |
205 | List<byte[]> param = new List<byte[]>(); | 205 | List<byte[]> param = new List<byte[]>(); |
206 | client.SendGenericMessage("WindlightReset", param); | 206 | client.SendGenericMessage("WindlightReset", UUID.Random(), param); |
207 | } | 207 | } |
208 | } | 208 | } |
209 | } | 209 | } |
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs index 396095a..03a96a4 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs | |||
@@ -44,14 +44,16 @@ using OpenSim.Tests.Common.Mock; | |||
44 | namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests | 44 | namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests |
45 | { | 45 | { |
46 | [TestFixture] | 46 | [TestFixture] |
47 | public class MoapTests | 47 | public class MoapTests : OpenSimTestCase |
48 | { | 48 | { |
49 | protected TestScene m_scene; | 49 | protected TestScene m_scene; |
50 | protected MoapModule m_module; | 50 | protected MoapModule m_module; |
51 | 51 | ||
52 | [SetUp] | 52 | [SetUp] |
53 | public void SetUp() | 53 | public override void SetUp() |
54 | { | 54 | { |
55 | base.SetUp(); | ||
56 | |||
55 | m_module = new MoapModule(); | 57 | m_module = new MoapModule(); |
56 | m_scene = new SceneHelpers().SetupScene(); | 58 | m_scene = new SceneHelpers().SetupScene(); |
57 | SceneHelpers.SetupSceneModules(m_scene, m_module); | 59 | SceneHelpers.SetupSceneModules(m_scene, m_module); |
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs index eb4731c..28daf2f 100644 --- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs | |||
@@ -38,6 +38,7 @@ using OpenSim.Region.Framework; | |||
38 | using OpenSim.Region.Framework.Interfaces; | 38 | using OpenSim.Region.Framework.Interfaces; |
39 | using OpenSim.Region.Framework.Scenes; | 39 | using OpenSim.Region.Framework.Scenes; |
40 | using OpenSim.Region.Framework.Scenes.Serialization; | 40 | using OpenSim.Region.Framework.Scenes.Serialization; |
41 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
41 | 42 | ||
42 | namespace OpenSim.Region.CoreModules.World.Objects.BuySell | 43 | namespace OpenSim.Region.CoreModules.World.Objects.BuySell |
43 | { | 44 | { |
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index ab8f143..e434b2e 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | |||
@@ -365,7 +365,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
365 | 365 | ||
366 | if (mainParams.Count < 4) | 366 | if (mainParams.Count < 4) |
367 | { | 367 | { |
368 | m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>"); | 368 | //m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>"); |
369 | m_console.OutputFormat("Usage: show part id <UUID-or-localID>"); | ||
369 | return; | 370 | return; |
370 | } | 371 | } |
371 | 372 | ||
@@ -405,6 +406,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
405 | 406 | ||
406 | if (mainParams.Count < 5) | 407 | if (mainParams.Count < 5) |
407 | { | 408 | { |
409 | //m_console.OutputFormat("Usage: show part pos <start-coord> to <end-coord>"); | ||
408 | m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>"); | 410 | m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>"); |
409 | return; | 411 | return; |
410 | } | 412 | } |
@@ -414,7 +416,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
414 | 416 | ||
415 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) | 417 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) |
416 | { | 418 | { |
417 | m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); | 419 | m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector); |
418 | return; | 420 | return; |
419 | } | 421 | } |
420 | 422 | ||
@@ -423,7 +425,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
423 | 425 | ||
424 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) | 426 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) |
425 | { | 427 | { |
426 | m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); | 428 | m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector); |
427 | return; | 429 | return; |
428 | } | 430 | } |
429 | 431 | ||
@@ -445,7 +447,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
445 | 447 | ||
446 | if (mainParams.Count < 4) | 448 | if (mainParams.Count < 4) |
447 | { | 449 | { |
448 | m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>"); | 450 | m_console.OutputFormat("Usage: show part name [--regex] <name>"); |
451 | //m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>"); | ||
449 | return; | 452 | return; |
450 | } | 453 | } |
451 | 454 | ||
@@ -577,6 +580,61 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
577 | cdl.AddRow("Link number", sop.LinkNum); | 580 | cdl.AddRow("Link number", sop.LinkNum); |
578 | cdl.AddRow("Flags", sop.Flags); | 581 | cdl.AddRow("Flags", sop.Flags); |
579 | 582 | ||
583 | if (showFull) | ||
584 | { | ||
585 | PrimitiveBaseShape s = sop.Shape; | ||
586 | cdl.AddRow("FlexiDrag", s.FlexiDrag); | ||
587 | cdl.AddRow("FlexiEntry", s.FlexiEntry); | ||
588 | cdl.AddRow("FlexiForce", string.Format("<{0},{1},{2}>", s.FlexiForceX, s.FlexiForceY, s.FlexiForceZ)); | ||
589 | cdl.AddRow("FlexiGravity", s.FlexiGravity); | ||
590 | cdl.AddRow("FlexiSoftness", s.FlexiSoftness); | ||
591 | cdl.AddRow("HollowShape", s.HollowShape); | ||
592 | cdl.AddRow( | ||
593 | "LightColor", | ||
594 | string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA)); | ||
595 | cdl.AddRow("LightCutoff", s.LightCutoff); | ||
596 | cdl.AddRow("LightEntry", s.LightEntry); | ||
597 | cdl.AddRow("LightFalloff", s.LightFalloff); | ||
598 | cdl.AddRow("LightIntensity", s.LightIntensity); | ||
599 | cdl.AddRow("LightRadius", s.LightRadius); | ||
600 | cdl.AddRow("Location (relative)", sop.RelativePosition); | ||
601 | cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a")); | ||
602 | cdl.AddRow("PathBegin", s.PathBegin); | ||
603 | cdl.AddRow("PathEnd", s.PathEnd); | ||
604 | cdl.AddRow("PathCurve", s.PathCurve); | ||
605 | cdl.AddRow("PathRadiusOffset", s.PathRadiusOffset); | ||
606 | cdl.AddRow("PathRevolutions", s.PathRevolutions); | ||
607 | cdl.AddRow("PathScale", string.Format("<{0},{1}>", s.PathScaleX, s.PathScaleY)); | ||
608 | cdl.AddRow("PathSkew", string.Format("<{0},{1}>", s.PathShearX, s.PathShearY)); | ||
609 | cdl.AddRow("FlexiDrag", s.PathSkew); | ||
610 | cdl.AddRow("PathTaper", string.Format("<{0},{1}>", s.PathTaperX, s.PathTaperY)); | ||
611 | cdl.AddRow("PathTwist", s.PathTwist); | ||
612 | cdl.AddRow("PathTwistBegin", s.PathTwistBegin); | ||
613 | cdl.AddRow("PCode", s.PCode); | ||
614 | cdl.AddRow("ProfileBegin", s.ProfileBegin); | ||
615 | cdl.AddRow("ProfileEnd", s.ProfileEnd); | ||
616 | cdl.AddRow("ProfileHollow", s.ProfileHollow); | ||
617 | cdl.AddRow("ProfileShape", s.ProfileShape); | ||
618 | cdl.AddRow("ProjectionAmbiance", s.ProjectionAmbiance); | ||
619 | cdl.AddRow("ProjectionEntry", s.ProjectionEntry); | ||
620 | cdl.AddRow("ProjectionFocus", s.ProjectionFocus); | ||
621 | cdl.AddRow("ProjectionFOV", s.ProjectionFOV); | ||
622 | cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID); | ||
623 | cdl.AddRow("Rotation (Relative)", sop.RotationOffset); | ||
624 | cdl.AddRow("Rotation (World)", sop.GetWorldRotation()); | ||
625 | cdl.AddRow("Scale", s.Scale); | ||
626 | cdl.AddRow( | ||
627 | "SculptData", | ||
628 | string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a")); | ||
629 | cdl.AddRow("SculptEntry", s.SculptEntry); | ||
630 | cdl.AddRow("SculptTexture", s.SculptTexture); | ||
631 | cdl.AddRow("SculptType", s.SculptType); | ||
632 | cdl.AddRow("State", s.State); | ||
633 | |||
634 | // TODO, unpack and display texture entries | ||
635 | //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures. | ||
636 | } | ||
637 | |||
580 | object itemsOutput; | 638 | object itemsOutput; |
581 | if (showFull) | 639 | if (showFull) |
582 | { | 640 | { |
@@ -588,7 +646,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
588 | itemsOutput = sop.Inventory.Count; | 646 | itemsOutput = sop.Inventory.Count; |
589 | } | 647 | } |
590 | 648 | ||
591 | |||
592 | cdl.AddRow("Items", itemsOutput); | 649 | cdl.AddRow("Items", itemsOutput); |
593 | 650 | ||
594 | return sb.Append(cdl.ToString()); | 651 | return sb.Append(cdl.ToString()); |
@@ -842,17 +899,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
842 | 899 | ||
843 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) | 900 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) |
844 | { | 901 | { |
845 | m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); | 902 | m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector); |
846 | endVector = Vector3.Zero; | 903 | endVector = Vector3.Zero; |
847 | 904 | ||
848 | return false; | 905 | return false; |
849 | } | 906 | } |
850 | 907 | ||
851 | string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); | 908 | string rawConsoleEndVector = rawComponents.Skip(2).Take(1).Single(); |
852 | 909 | ||
853 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) | 910 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) |
854 | { | 911 | { |
855 | m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); | 912 | m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector); |
856 | return false; | 913 | return false; |
857 | } | 914 | } |
858 | 915 | ||
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index ddaa227..79dd4a0 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | |||
@@ -38,6 +38,7 @@ using OpenSim.Region.Framework.Scenes; | |||
38 | using OpenSim.Services.Interfaces; | 38 | using OpenSim.Services.Interfaces; |
39 | 39 | ||
40 | using Mono.Addins; | 40 | using Mono.Addins; |
41 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
41 | 42 | ||
42 | namespace OpenSim.Region.CoreModules.World.Permissions | 43 | namespace OpenSim.Region.CoreModules.World.Permissions |
43 | { | 44 | { |
@@ -156,9 +157,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
156 | 157 | ||
157 | public void Initialise(IConfigSource config) | 158 | public void Initialise(IConfigSource config) |
158 | { | 159 | { |
159 | IConfig myConfig = config.Configs["Startup"]; | 160 | string permissionModules = Util.GetConfigVarFromSections<string>(config, "permissionmodules", |
160 | 161 | new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule"); | |
161 | string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); | ||
162 | 162 | ||
163 | List<string> modules = new List<string>(permissionModules.Split(',')); | 163 | List<string> modules = new List<string>(permissionModules.Split(',')); |
164 | 164 | ||
@@ -167,26 +167,34 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
167 | 167 | ||
168 | m_Enabled = true; | 168 | m_Enabled = true; |
169 | 169 | ||
170 | m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false); | 170 | m_allowGridGods = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", |
171 | m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true); | 171 | new string[] { "Startup", "Permissions" }, false); |
172 | m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true); | 172 | m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions", |
173 | m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true); | 173 | new string[] { "Startup", "Permissions" }, true); |
174 | m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false); | 174 | m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions", |
175 | m_ParcelOwnerIsGod = myConfig.GetBoolean("parcel_owner_is_god", true); | 175 | new string[] { "Startup", "Permissions" }, true); |
176 | 176 | m_RegionOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god", | |
177 | m_SimpleBuildPermissions = myConfig.GetBoolean("simple_build_permissions", false); | 177 | new string[] { "Startup", "Permissions" }, true); |
178 | m_RegionManagerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god", | ||
179 | new string[] { "Startup", "Permissions" }, false); | ||
180 | m_ParcelOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "parcel_owner_is_god", | ||
181 | new string[] { "Startup", "Permissions" }, true); | ||
182 | |||
183 | m_SimpleBuildPermissions = Util.GetConfigVarFromSections<bool>(config, "simple_build_permissions", | ||
184 | new string[] { "Startup", "Permissions" }, false); | ||
178 | 185 | ||
179 | m_allowedScriptCreators | 186 | m_allowedScriptCreators |
180 | = ParseUserSetConfigSetting(myConfig, "allowed_script_creators", m_allowedScriptCreators); | 187 | = ParseUserSetConfigSetting(config, "allowed_script_creators", m_allowedScriptCreators); |
181 | m_allowedScriptEditors | 188 | m_allowedScriptEditors |
182 | = ParseUserSetConfigSetting(myConfig, "allowed_script_editors", m_allowedScriptEditors); | 189 | = ParseUserSetConfigSetting(config, "allowed_script_editors", m_allowedScriptEditors); |
183 | 190 | ||
184 | if (m_bypassPermissions) | 191 | if (m_bypassPermissions) |
185 | m_log.Info("[PERMISSIONS]: serverside_object_permissions = false in ini file so disabling all region service permission checks"); | 192 | m_log.Info("[PERMISSIONS]: serverside_object_permissions = false in ini file so disabling all region service permission checks"); |
186 | else | 193 | else |
187 | m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); | 194 | m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); |
188 | 195 | ||
189 | string grant = myConfig.GetString("GrantLSL", ""); | 196 | string grant = Util.GetConfigVarFromSections<string>(config, "GrantLSL", |
197 | new string[] { "Startup", "Permissions" }, string.Empty); | ||
190 | if (grant.Length > 0) | 198 | if (grant.Length > 0) |
191 | { | 199 | { |
192 | foreach (string uuidl in grant.Split(',')) | 200 | foreach (string uuidl in grant.Split(',')) |
@@ -196,7 +204,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
196 | } | 204 | } |
197 | } | 205 | } |
198 | 206 | ||
199 | grant = myConfig.GetString("GrantCS", ""); | 207 | grant = Util.GetConfigVarFromSections<string>(config, "GrantCS", |
208 | new string[] { "Startup", "Permissions" }, string.Empty); | ||
200 | if (grant.Length > 0) | 209 | if (grant.Length > 0) |
201 | { | 210 | { |
202 | foreach (string uuidl in grant.Split(',')) | 211 | foreach (string uuidl in grant.Split(',')) |
@@ -206,7 +215,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
206 | } | 215 | } |
207 | } | 216 | } |
208 | 217 | ||
209 | grant = myConfig.GetString("GrantVB", ""); | 218 | grant = Util.GetConfigVarFromSections<string>(config, "GrantVB", |
219 | new string[] { "Startup", "Permissions" }, string.Empty); | ||
210 | if (grant.Length > 0) | 220 | if (grant.Length > 0) |
211 | { | 221 | { |
212 | foreach (string uuidl in grant.Split(',')) | 222 | foreach (string uuidl in grant.Split(',')) |
@@ -216,7 +226,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
216 | } | 226 | } |
217 | } | 227 | } |
218 | 228 | ||
219 | grant = myConfig.GetString("GrantJS", ""); | 229 | grant = Util.GetConfigVarFromSections<string>(config, "GrantJS", |
230 | new string[] { "Startup", "Permissions" }, string.Empty); | ||
220 | if (grant.Length > 0) | 231 | if (grant.Length > 0) |
221 | { | 232 | { |
222 | foreach (string uuidl in grant.Split(',')) | 233 | foreach (string uuidl in grant.Split(',')) |
@@ -226,7 +237,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
226 | } | 237 | } |
227 | } | 238 | } |
228 | 239 | ||
229 | grant = myConfig.GetString("GrantYP", ""); | 240 | grant = Util.GetConfigVarFromSections<string>(config, "GrantYP", |
241 | new string[] { "Startup", "Permissions" }, string.Empty); | ||
230 | if (grant.Length > 0) | 242 | if (grant.Length > 0) |
231 | { | 243 | { |
232 | foreach (string uuidl in grant.Split(',')) | 244 | foreach (string uuidl in grant.Split(',')) |
@@ -464,11 +476,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
464 | /// <param name="settingName"></param> | 476 | /// <param name="settingName"></param> |
465 | /// <param name="defaultValue">The default value for this attribute</param> | 477 | /// <param name="defaultValue">The default value for this attribute</param> |
466 | /// <returns>The parsed value</returns> | 478 | /// <returns>The parsed value</returns> |
467 | private static UserSet ParseUserSetConfigSetting(IConfig config, string settingName, UserSet defaultValue) | 479 | private static UserSet ParseUserSetConfigSetting(IConfigSource config, string settingName, UserSet defaultValue) |
468 | { | 480 | { |
469 | UserSet userSet = defaultValue; | 481 | UserSet userSet = defaultValue; |
470 | 482 | ||
471 | string rawSetting = config.GetString(settingName, defaultValue.ToString()); | 483 | string rawSetting = Util.GetConfigVarFromSections<string>(config, settingName, |
484 | new string[] {"Startup", "Permissions"}, defaultValue.ToString()); | ||
472 | 485 | ||
473 | // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term | 486 | // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term |
474 | // this should disappear. | 487 | // this should disappear. |
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index 7825e3e..b4348c9 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs | |||
@@ -35,11 +35,12 @@ using OpenSim.Framework; | |||
35 | using OpenSim.Region.Framework.Scenes; | 35 | using OpenSim.Region.Framework.Scenes; |
36 | using OpenSim.Region.Framework.Scenes.Serialization; | 36 | using OpenSim.Region.Framework.Scenes.Serialization; |
37 | using OpenSim.Tests.Common; | 37 | using OpenSim.Tests.Common; |
38 | using OpenMetaverse.StructuredData; | ||
38 | 39 | ||
39 | namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | 40 | namespace OpenSim.Region.CoreModules.World.Serialiser.Tests |
40 | { | 41 | { |
41 | [TestFixture] | 42 | [TestFixture] |
42 | public class SerialiserTests | 43 | public class SerialiserTests : OpenSimTestCase |
43 | { | 44 | { |
44 | private string xml = @" | 45 | private string xml = @" |
45 | <SceneObjectGroup> | 46 | <SceneObjectGroup> |
@@ -143,6 +144,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
143 | <Flags>None</Flags> | 144 | <Flags>None</Flags> |
144 | <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound> | 145 | <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound> |
145 | <CollisionSoundVolume>0</CollisionSoundVolume> | 146 | <CollisionSoundVolume>0</CollisionSoundVolume> |
147 | <DynAttrs><llsd><map><key>MyStore</key><map><key>the answer</key><integer>42</integer></map></map></llsd></DynAttrs> | ||
146 | </SceneObjectPart> | 148 | </SceneObjectPart> |
147 | </RootPart> | 149 | </RootPart> |
148 | <OtherParts /> | 150 | <OtherParts /> |
@@ -331,6 +333,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
331 | <EveryoneMask>0</EveryoneMask> | 333 | <EveryoneMask>0</EveryoneMask> |
332 | <NextOwnerMask>2147483647</NextOwnerMask> | 334 | <NextOwnerMask>2147483647</NextOwnerMask> |
333 | <Flags>None</Flags> | 335 | <Flags>None</Flags> |
336 | <DynAttrs><llsd><map><key>MyStore</key><map><key>last words</key><string>Rosebud</string></map></map></llsd></DynAttrs> | ||
334 | <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar> | 337 | <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar> |
335 | </SceneObjectPart> | 338 | </SceneObjectPart> |
336 | <OtherParts /> | 339 | <OtherParts /> |
@@ -359,6 +362,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
359 | Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); | 362 | Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); |
360 | Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); | 363 | Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); |
361 | Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); | 364 | Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); |
365 | OSDMap store = rootPart.DynAttrs["MyStore"]; | ||
366 | Assert.AreEqual(42, store["the answer"].AsInteger()); | ||
362 | 367 | ||
363 | // TODO: Check other properties | 368 | // TODO: Check other properties |
364 | } | 369 | } |
@@ -409,6 +414,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
409 | rp.CreatorID = rpCreatorId; | 414 | rp.CreatorID = rpCreatorId; |
410 | rp.Shape = shape; | 415 | rp.Shape = shape; |
411 | 416 | ||
417 | string daStoreName = "MyStore"; | ||
418 | string daKey = "foo"; | ||
419 | string daValue = "bar"; | ||
420 | OSDMap myStore = new OSDMap(); | ||
421 | myStore.Add(daKey, daValue); | ||
422 | rp.DynAttrs = new DAMap(); | ||
423 | rp.DynAttrs[daStoreName] = myStore; | ||
424 | |||
412 | SceneObjectGroup so = new SceneObjectGroup(rp); | 425 | SceneObjectGroup so = new SceneObjectGroup(rp); |
413 | 426 | ||
414 | // Need to add the object to the scene so that the request to get script state succeeds | 427 | // Need to add the object to the scene so that the request to get script state succeeds |
@@ -424,6 +437,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
424 | UUID uuid = UUID.Zero; | 437 | UUID uuid = UUID.Zero; |
425 | string name = null; | 438 | string name = null; |
426 | UUID creatorId = UUID.Zero; | 439 | UUID creatorId = UUID.Zero; |
440 | DAMap daMap = null; | ||
427 | 441 | ||
428 | while (xtr.Read() && xtr.Name != "SceneObjectPart") | 442 | while (xtr.Read() && xtr.Name != "SceneObjectPart") |
429 | { | 443 | { |
@@ -449,6 +463,10 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
449 | creatorId = UUID.Parse(xtr.ReadElementString("UUID")); | 463 | creatorId = UUID.Parse(xtr.ReadElementString("UUID")); |
450 | xtr.ReadEndElement(); | 464 | xtr.ReadEndElement(); |
451 | break; | 465 | break; |
466 | case "DynAttrs": | ||
467 | daMap = new DAMap(); | ||
468 | daMap.ReadXml(xtr); | ||
469 | break; | ||
452 | } | 470 | } |
453 | } | 471 | } |
454 | 472 | ||
@@ -462,6 +480,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
462 | Assert.That(uuid, Is.EqualTo(rpUuid)); | 480 | Assert.That(uuid, Is.EqualTo(rpUuid)); |
463 | Assert.That(name, Is.EqualTo(rpName)); | 481 | Assert.That(name, Is.EqualTo(rpName)); |
464 | Assert.That(creatorId, Is.EqualTo(rpCreatorId)); | 482 | Assert.That(creatorId, Is.EqualTo(rpCreatorId)); |
483 | Assert.NotNull(daMap); | ||
484 | Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); | ||
465 | } | 485 | } |
466 | 486 | ||
467 | [Test] | 487 | [Test] |
@@ -476,6 +496,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
476 | Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); | 496 | Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); |
477 | Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); | 497 | Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); |
478 | Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); | 498 | Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); |
499 | OSDMap store = rootPart.DynAttrs["MyStore"]; | ||
500 | Assert.AreEqual("Rosebud", store["last words"].AsString()); | ||
479 | 501 | ||
480 | // TODO: Check other properties | 502 | // TODO: Check other properties |
481 | } | 503 | } |
@@ -500,6 +522,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
500 | rp.CreatorID = rpCreatorId; | 522 | rp.CreatorID = rpCreatorId; |
501 | rp.Shape = shape; | 523 | rp.Shape = shape; |
502 | 524 | ||
525 | string daStoreName = "MyStore"; | ||
526 | string daKey = "foo"; | ||
527 | string daValue = "bar"; | ||
528 | OSDMap myStore = new OSDMap(); | ||
529 | myStore.Add(daKey, daValue); | ||
530 | rp.DynAttrs = new DAMap(); | ||
531 | rp.DynAttrs[daStoreName] = myStore; | ||
532 | |||
503 | SceneObjectGroup so = new SceneObjectGroup(rp); | 533 | SceneObjectGroup so = new SceneObjectGroup(rp); |
504 | 534 | ||
505 | // Need to add the object to the scene so that the request to get script state succeeds | 535 | // Need to add the object to the scene so that the request to get script state succeeds |
@@ -516,6 +546,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
516 | UUID uuid = UUID.Zero; | 546 | UUID uuid = UUID.Zero; |
517 | string name = null; | 547 | string name = null; |
518 | UUID creatorId = UUID.Zero; | 548 | UUID creatorId = UUID.Zero; |
549 | DAMap daMap = null; | ||
519 | 550 | ||
520 | while (xtr.Read() && xtr.Name != "SceneObjectPart") | 551 | while (xtr.Read() && xtr.Name != "SceneObjectPart") |
521 | { | 552 | { |
@@ -537,6 +568,10 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
537 | creatorId = UUID.Parse(xtr.ReadElementString("Guid")); | 568 | creatorId = UUID.Parse(xtr.ReadElementString("Guid")); |
538 | xtr.ReadEndElement(); | 569 | xtr.ReadEndElement(); |
539 | break; | 570 | break; |
571 | case "DynAttrs": | ||
572 | daMap = new DAMap(); | ||
573 | daMap.ReadXml(xtr); | ||
574 | break; | ||
540 | } | 575 | } |
541 | } | 576 | } |
542 | 577 | ||
@@ -549,6 +584,8 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests | |||
549 | Assert.That(uuid, Is.EqualTo(rpUuid)); | 584 | Assert.That(uuid, Is.EqualTo(rpUuid)); |
550 | Assert.That(name, Is.EqualTo(rpName)); | 585 | Assert.That(name, Is.EqualTo(rpName)); |
551 | Assert.That(creatorId, Is.EqualTo(rpCreatorId)); | 586 | Assert.That(creatorId, Is.EqualTo(rpCreatorId)); |
587 | Assert.NotNull(daMap); | ||
588 | Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); | ||
552 | } | 589 | } |
553 | } | 590 | } |
554 | } \ No newline at end of file | 591 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 513a8f5..883045a 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs | |||
@@ -43,8 +43,8 @@ namespace OpenSim.Region.CoreModules.World.Sound | |||
43 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] | 43 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] |
44 | public class SoundModule : INonSharedRegionModule, ISoundModule | 44 | public class SoundModule : INonSharedRegionModule, ISoundModule |
45 | { | 45 | { |
46 | private static readonly ILog m_log = LogManager.GetLogger( | 46 | // private static readonly ILog m_log = LogManager.GetLogger( |
47 | MethodBase.GetCurrentMethod().DeclaringType); | 47 | // MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | private Scene m_scene; | 49 | private Scene m_scene; |
50 | 50 | ||
@@ -76,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Sound | |||
76 | 76 | ||
77 | public void RemoveRegion(Scene scene) | 77 | public void RemoveRegion(Scene scene) |
78 | { | 78 | { |
79 | m_scene.EventManager.OnClientLogin -= OnNewClient; | 79 | m_scene.EventManager.OnNewClient -= OnNewClient; |
80 | } | 80 | } |
81 | 81 | ||
82 | public void RegionLoaded(Scene scene) | 82 | public void RegionLoaded(Scene scene) |
@@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.World.Sound | |||
85 | return; | 85 | return; |
86 | 86 | ||
87 | m_scene = scene; | 87 | m_scene = scene; |
88 | m_scene.EventManager.OnClientLogin += OnNewClient; | 88 | m_scene.EventManager.OnNewClient += OnNewClient; |
89 | 89 | ||
90 | m_scene.RegisterModuleInterface<ISoundModule>(this); | 90 | m_scene.RegisterModuleInterface<ISoundModule>(this); |
91 | } | 91 | } |
diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs index a321c09..6f344c8 100644 --- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs +++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs | |||
@@ -252,12 +252,11 @@ namespace OpenSim.Region.CoreModules | |||
252 | } | 252 | } |
253 | 253 | ||
254 | // TODO: Decouple this, so we can get rid of Linden Hour info | 254 | // TODO: Decouple this, so we can get rid of Linden Hour info |
255 | // Update Region infor with new Sun Position and Hour | 255 | // Update Region with new Sun Vector |
256 | // set estate settings for region access to sun position | 256 | // set estate settings for region access to sun position |
257 | if (receivedEstateToolsSunUpdate) | 257 | if (receivedEstateToolsSunUpdate) |
258 | { | 258 | { |
259 | m_scene.RegionInfo.RegionSettings.SunVector = Position; | 259 | m_scene.RegionInfo.RegionSettings.SunVector = Position; |
260 | m_scene.RegionInfo.RegionSettings.SunPosition = GetCurrentTimeAsLindenSunHour(); | ||
261 | } | 260 | } |
262 | } | 261 | } |
263 | 262 | ||
@@ -395,7 +394,7 @@ namespace OpenSim.Region.CoreModules | |||
395 | ready = false; | 394 | ready = false; |
396 | 395 | ||
397 | // Remove our hooks | 396 | // Remove our hooks |
398 | m_scene.EventManager.OnFrame -= SunUpdate; | 397 | m_scene.EventManager.OnFrame -= SunUpdate; |
399 | m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; | 398 | m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; |
400 | m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate; | 399 | m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate; |
401 | m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; | 400 | m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; |
@@ -459,26 +458,33 @@ namespace OpenSim.Region.CoreModules | |||
459 | SunToClient(avatar.ControllingClient); | 458 | SunToClient(avatar.ControllingClient); |
460 | } | 459 | } |
461 | 460 | ||
462 | /// <summary> | 461 | public void EstateToolsSunUpdate(ulong regionHandle) |
463 | /// | ||
464 | /// </summary> | ||
465 | /// <param name="regionHandle"></param> | ||
466 | /// <param name="FixedTime">Is the sun's position fixed?</param> | ||
467 | /// <param name="useEstateTime">Use the Region or Estate Sun hour?</param> | ||
468 | /// <param name="FixedSunHour">What hour of the day is the Sun Fixed at?</param> | ||
469 | public void EstateToolsSunUpdate(ulong regionHandle, bool FixedSun, bool useEstateTime, float FixedSunHour) | ||
470 | { | 462 | { |
471 | if (m_scene.RegionInfo.RegionHandle == regionHandle) | 463 | if (m_scene.RegionInfo.RegionHandle == regionHandle) |
472 | { | 464 | { |
473 | // Must limit the Sun Hour to 0 ... 24 | 465 | float sunFixedHour; |
474 | while (FixedSunHour > 24.0f) | 466 | bool fixedSun; |
475 | FixedSunHour -= 24; | ||
476 | 467 | ||
477 | while (FixedSunHour < 0) | 468 | if (m_scene.RegionInfo.RegionSettings.UseEstateSun) |
478 | FixedSunHour += 24; | 469 | { |
470 | sunFixedHour = (float)m_scene.RegionInfo.EstateSettings.SunPosition; | ||
471 | fixedSun = m_scene.RegionInfo.EstateSettings.FixedSun; | ||
472 | } | ||
473 | else | ||
474 | { | ||
475 | sunFixedHour = (float)m_scene.RegionInfo.RegionSettings.SunPosition - 6.0f; | ||
476 | fixedSun = m_scene.RegionInfo.RegionSettings.FixedSun; | ||
477 | } | ||
478 | |||
479 | // Must limit the Sun Hour to 0 ... 24 | ||
480 | while (sunFixedHour > 24.0f) | ||
481 | sunFixedHour -= 24; | ||
479 | 482 | ||
480 | m_SunFixedHour = FixedSunHour; | 483 | while (sunFixedHour < 0) |
481 | m_SunFixed = FixedSun; | 484 | sunFixedHour += 24; |
485 | |||
486 | m_SunFixedHour = sunFixedHour; | ||
487 | m_SunFixed = fixedSun; | ||
482 | 488 | ||
483 | // m_log.DebugFormat("[SUN]: Sun Settings Update: Fixed Sun? : {0}", m_SunFixed.ToString()); | 489 | // m_log.DebugFormat("[SUN]: Sun Settings Update: Fixed Sun? : {0}", m_SunFixed.ToString()); |
484 | // m_log.DebugFormat("[SUN]: Sun Settings Update: Sun Hour : {0}", m_SunFixedHour.ToString()); | 490 | // m_log.DebugFormat("[SUN]: Sun Settings Update: Sun Hour : {0}", m_SunFixedHour.ToString()); |
@@ -501,7 +507,7 @@ namespace OpenSim.Region.CoreModules | |||
501 | { | 507 | { |
502 | m_scene.ForEachRootClient(delegate(IClientAPI client) | 508 | m_scene.ForEachRootClient(delegate(IClientAPI client) |
503 | { | 509 | { |
504 | SunToClient(client); | 510 | SunToClient(client); |
505 | }); | 511 | }); |
506 | } | 512 | } |
507 | 513 | ||
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 33aabe4..4d738a5 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | |||
@@ -480,7 +480,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
480 | else | 480 | else |
481 | { | 481 | { |
482 | m_plugineffects[pluginName] = effect; | 482 | m_plugineffects[pluginName] = effect; |
483 | m_log.Warn("E ... " + pluginName + " (Replaced)"); | 483 | m_log.Info("E ... " + pluginName + " (Replaced)"); |
484 | } | 484 | } |
485 | } | 485 | } |
486 | } | 486 | } |
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs index 3d4f762..be719ea 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs | |||
@@ -30,11 +30,12 @@ using NUnit.Framework; | |||
30 | using OpenSim.Framework; | 30 | using OpenSim.Framework; |
31 | using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; | 31 | using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; |
32 | using OpenSim.Region.Framework.Scenes; | 32 | using OpenSim.Region.Framework.Scenes; |
33 | using OpenSim.Tests.Common; | ||
33 | 34 | ||
34 | namespace OpenSim.Region.CoreModules.World.Terrain.Tests | 35 | namespace OpenSim.Region.CoreModules.World.Terrain.Tests |
35 | { | 36 | { |
36 | [TestFixture] | 37 | [TestFixture] |
37 | public class TerrainTest | 38 | public class TerrainTest : OpenSimTestCase |
38 | { | 39 | { |
39 | [Test] | 40 | [Test] |
40 | public void BrushTest() | 41 | public void BrushTest() |
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 7ef44db..d38f34b 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | |||
@@ -74,8 +74,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
74 | { | 74 | { |
75 | m_config = source; | 75 | m_config = source; |
76 | 76 | ||
77 | IConfig startupConfig = m_config.Configs["Startup"]; | 77 | if (Util.GetConfigVarFromSections<string>( |
78 | if (startupConfig.GetString("MapImageModule", "MapImageModule") != "Warp3DImageModule") | 78 | m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "Warp3DImageModule") |
79 | return; | 79 | return; |
80 | 80 | ||
81 | m_Enabled = true; | 81 | m_Enabled = true; |
@@ -157,16 +157,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
157 | bool drawPrimVolume = true; | 157 | bool drawPrimVolume = true; |
158 | bool textureTerrain = true; | 158 | bool textureTerrain = true; |
159 | 159 | ||
160 | try | 160 | string[] configSections = new string[] { "Map", "Startup" }; |
161 | { | 161 | |
162 | IConfig startupConfig = m_config.Configs["Startup"]; | 162 | drawPrimVolume |
163 | drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume); | 163 | = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume); |
164 | textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain); | 164 | textureTerrain |
165 | } | 165 | = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain); |
166 | catch | ||
167 | { | ||
168 | m_log.Warn("[WARP 3D IMAGE MODULE]: Failed to load StartupConfig"); | ||
169 | } | ||
170 | 166 | ||
171 | m_colors.Clear(); | 167 | m_colors.Clear(); |
172 | 168 | ||
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs index fd8e2b4..9de588c 100644 --- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs +++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs | |||
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules | |||
66 | public void Initialise(IConfigSource config) | 66 | public void Initialise(IConfigSource config) |
67 | { | 67 | { |
68 | m_windConfig = config.Configs["Wind"]; | 68 | m_windConfig = config.Configs["Wind"]; |
69 | string desiredWindPlugin = m_dWindPluginName; | 69 | // string desiredWindPlugin = m_dWindPluginName; |
70 | 70 | ||
71 | if (m_windConfig != null) | 71 | if (m_windConfig != null) |
72 | { | 72 | { |
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 2184a59..bf18616 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | |||
@@ -89,11 +89,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
89 | #region INonSharedRegionModule Members | 89 | #region INonSharedRegionModule Members |
90 | public virtual void Initialise (IConfigSource config) | 90 | public virtual void Initialise (IConfigSource config) |
91 | { | 91 | { |
92 | IConfig startupConfig = config.Configs["Startup"]; | 92 | string[] configSections = new string[] { "Map", "Startup" }; |
93 | if (startupConfig.GetString("WorldMapModule", "WorldMap") == "WorldMap") | ||
94 | m_Enabled = true; | ||
95 | 93 | ||
96 | blacklistTimeout = startupConfig.GetInt("BlacklistTimeout", 10*60) * 1000; | 94 | if (Util.GetConfigVarFromSections<string>( |
95 | config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") | ||
96 | m_Enabled = true; | ||
97 | |||
98 | blacklistTimeout | ||
99 | = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000; | ||
97 | } | 100 | } |
98 | 101 | ||
99 | public virtual void AddRegion (Scene scene) | 102 | public virtual void AddRegion (Scene scene) |