From 541a7660e06206c9a9eb2426dee0449afb554921 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Tue, 23 Nov 2010 16:08:10 -0800 Subject: Refactor appearance and avatar data sending code. Paritioning the routines into "one-to-many" and "many-to-one" makes it possible to call the right function on presence creation (both child and root) and when a child agent is promoted to root. This brings the total number of appearance sends down to one or two on login. Cleaned up the avatar update calls in the groups code. Cleaned up some commented and debugging code, and a few formating fixes. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 30 +++++----------------- 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 0df4585..ab1c206 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory }); } - // m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); + m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); } // Process the visual params, this may change height as well @@ -196,12 +196,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory sp.SetHeight(sp.Appearance.AvatarHeight); } } - - // Send the appearance back to the avatar, not clear that this is needed - sp.ControllingClient.SendAvatarDataImmediate(sp); - // AvatarAppearance avp = sp.Appearance; - // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); - } @@ -274,21 +268,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Send the appearance to everyone in the scene sp.SendAppearanceToAllOtherAgents(); - // sp.ControllingClient.SendAvatarDataImmediate(sp); - - // Send the appearance back to the avatar - // AvatarAppearance avp = sp.Appearance; - // sp.ControllingClient.SendAppearance(avp.Owner, avp.VisualParams, avp.Texture.GetBytes()); - -/* -// this needs to be fixed, the flag should be on scene presence not the region module - // Start the animations if necessary - if (!m_startAnimationSet) - { - sp.Animator.UpdateMovementAnimations(); - m_startAnimationSet = true; - } -*/ } private void HandleAppearanceSave(UUID agentid) @@ -374,6 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); + // operate on a copy of the appearance so we don't have to lock anything AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) @@ -388,9 +368,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory SetAppearanceAssets(sp.UUID, ref avatAppearance); // could get fancier with the locks here, but in the spirit of "last write wins" - // this should work correctly + // this should work correctly, also, we don't need to send the appearance here + // since the "iswearing" will trigger a new set of visual param and baked texture changes + // when those complete, the new appearance will be sent sp.Appearance = avatAppearance; - m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); + QueueAppearanceSave(client.AgentId); } private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) -- cgit v1.1 From f86c438653fc3c8356a8f0c43a055b1928183f02 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 29 Nov 2010 08:43:33 -0800 Subject: Preservation of creator information now also working in IARs. Cleaned up usage help. Moved Osp around, deleted unnecessary OspInventoryWrapperPlugin, added manipulation of SOP's xml representation in a generic ExternalRepresentationUtils function. --- .../Archiver/InventoryArchiveReadRequest.cs | 11 +++-- .../Archiver/InventoryArchiveWriteRequest.cs | 28 ++++++----- .../Inventory/Archiver/InventoryArchiverModule.cs | 54 +++++++++++++++++----- .../Archiver/Tests/InventoryArchiverTests.cs | 5 +- 4 files changed, 63 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 046b05f..870ead2 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -37,12 +37,11 @@ using System.Xml.Linq; using log4net; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Osp; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; using OpenSim.Region.CoreModules.World.Archiver; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver @@ -398,16 +397,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Don't use the item ID that's in the file item.ID = UUID.Random(); - UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); - if (UUID.Zero != ospResolvedId) + UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); + if (UUID.Zero != ospResolvedId) // The user exists in this grid { item.CreatorIdAsUuid = ospResolvedId; // XXX: For now, don't preserve the OSPA in the creator id (which actually gets persisted to the // database). Instead, replace with the UUID that we found. item.CreatorId = ospResolvedId.ToString(); + + item.CreatorData = string.Empty; } - else + else if (item.CreatorData == null || item.CreatorData == String.Empty) { item.CreatorIdAsUuid = m_userInfo.PrincipalID; } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d81703a..cab341d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -36,8 +36,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Osp; using OpenSim.Region.CoreModules.World.Archiver; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -139,20 +137,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); } - protected void SaveInvItem(InventoryItemBase inventoryItem, string path) + protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary options, IUserAccountService userAccountService) { string filename = path + CreateArchiveItemName(inventoryItem); // Record the creator of this item for user record purposes (which might go away soon) m_userUuids[inventoryItem.CreatorIdAsUuid] = 1; - InventoryItemBase saveItem = (InventoryItemBase)inventoryItem.Clone(); - saveItem.CreatorId = OspResolver.MakeOspa(saveItem.CreatorIdAsUuid, m_scene.UserAccountService); - - string serialization = UserInventoryItemSerializer.Serialize(saveItem); + string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); m_archiveWriter.WriteFile(filename, serialization); - m_assetGatherer.GatherAssetUuids(saveItem.AssetID, (AssetType)saveItem.AssetType, m_assetUuids); + m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); } /// @@ -161,7 +156,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// The inventory folder to save /// The path to which the folder should be saved /// If true, save this folder itself. If false, only saves contents - protected void SaveInvFolder(InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself) + protected void SaveInvFolder(InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, Dictionary options, IUserAccountService userAccountService) { if (saveThisFolderItself) { @@ -176,19 +171,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver foreach (InventoryFolderBase childFolder in contents.Folders) { - SaveInvFolder(childFolder, path, true); + SaveInvFolder(childFolder, path, true, options, userAccountService); } foreach (InventoryItemBase item in contents.Items) { - SaveInvItem(item, path); + SaveInvItem(item, path, options, userAccountService); } } /// /// Execute the inventory write request /// - public void Execute() + public void Execute(Dictionary options, IUserAccountService userAccountService) { try { @@ -266,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); //recurse through all dirs getting dirs and files - SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly); + SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService); } else if (inventoryItem != null) { @@ -274,14 +269,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, m_invPath); - SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH); + SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService); } // Don't put all this profile information into the archive right now. //SaveUsers(); new AssetsRequest( - new AssetsArchiver(m_archiveWriter), m_assetUuids, m_scene.AssetService, ReceivedAllAssets).Execute(); + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets).Execute(); } catch (Exception) { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 2eaca49..421ea30 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -75,6 +75,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver private Dictionary m_scenes = new Dictionary(); private Scene m_aScene; + private IUserAccountService m_UserAccountService; + protected IUserAccountService UserAccountService + { + get + { + if (m_UserAccountService == null) + // What a strange thing to do... + foreach (Scene s in m_scenes.Values) + { + m_UserAccountService = s.RequestModuleInterface(); + break; + } + + return m_UserAccountService; + } + } + + public InventoryArchiverModule() {} public InventoryArchiverModule(bool disablePresenceChecks) @@ -106,11 +124,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "save iar", - "save iar []", + "save iar [--p|-profile=] []", "Save user inventory archive (IAR).", " is the user's first name." + Environment.NewLine + " is the user's last name." + Environment.NewLine + " is the path inside the user's inventory for the folder/item to be saved." + Environment.NewLine + + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + " is the filesystem path at which to save the IAR." + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), HandleSaveInvConsoleCommand); @@ -157,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { try { - new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream).Execute(); + new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream).Execute(options, UserAccountService); } catch (EntryPointNotFoundException e) { @@ -197,7 +216,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { try { - new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath).Execute(); + new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath).Execute(options, UserAccountService); } catch (EntryPointNotFoundException e) { @@ -368,10 +387,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void HandleSaveInvConsoleCommand(string module, string[] cmdparams) { Guid id = Guid.NewGuid(); - + + Dictionary options = new Dictionary(); + + OptionSet ops = new OptionSet(); + //ops.Add("v|version=", delegate(string v) { options["version"] = v; }); + ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); + + List mainParams = ops.Parse(cmdparams); + try { - if (cmdparams.Length < 6) + if (mainParams.Count < 6) { m_log.Error( "[INVENTORY ARCHIVER]: usage is save iar []"); @@ -379,18 +406,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); - - string firstName = cmdparams[2]; - string lastName = cmdparams[3]; - string invPath = cmdparams[4]; - string pass = cmdparams[5]; - string savePath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); + if (options.ContainsKey("profile")) + m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -profile option if you want to produce a compatible IAR"); + + string firstName = mainParams[2]; + string lastName = mainParams[3]; + string invPath = mainParams[4]; + string pass = mainParams[5]; + string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", savePath, invPath, firstName, lastName); - ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary()); + ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options); } catch (InventoryArchiverException e) { @@ -518,5 +547,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } + } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 938886b2..1e39c39 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -38,7 +38,6 @@ using OpenSim.Framework; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Osp; using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.Framework.Scenes; @@ -103,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string item1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); - tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); + tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), null)); tar.Close(); m_iarStream = new MemoryStream(archiveWriteStream.ToArray()); } @@ -551,7 +550,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string item1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); - tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); + tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), null)); tar.Close(); MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); -- cgit v1.1 From 49b59fffee54bb7aa7db2382ba564c99368945d4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 29 Nov 2010 09:57:41 -0800 Subject: Fix unit test. --- .../Inventory/Archiver/InventoryArchiveReadRequest.cs | 2 +- .../Avatar/Inventory/Archiver/InventoryArchiverModule.cs | 10 +++++++--- .../Inventory/Archiver/Tests/InventoryArchiverTests.cs | 13 ++++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 870ead2..acf2c3e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -412,7 +412,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { item.CreatorIdAsUuid = m_userInfo.PrincipalID; } - + item.Owner = m_userInfo.PrincipalID; // Reset folder ID to the one in which we want to load it diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 421ea30..b33c2b1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -254,14 +254,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (m_scenes.Count > 0) { UserAccount userInfo = GetUserInfo(firstName, lastName, pass); - + if (userInfo != null) { if (CheckPresence(userInfo.PrincipalID)) { + InventoryArchiveReadRequest request; bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); - + try { request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge); @@ -275,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + UpdateClientWithLoadedNodes(userInfo, request.Execute()); return true; @@ -287,6 +288,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID); } } + else + m_log.ErrorFormat("[INVENTORY ARCHIVER]: User {0} {1} not found", + firstName, lastName); } return false; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 1e39c39..2747e15 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -95,14 +95,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests item1.Name = m_item1Name; item1.AssetID = UUID.Random(); item1.GroupID = UUID.Random(); - item1.CreatorId = OspResolver.MakeOspa(m_ua2.FirstName, m_ua2.LastName); + //item1.CreatorId = OspResolver.MakeOspa(m_ua2.FirstName, m_ua2.LastName); //item1.CreatorId = userUuid.ToString(); - //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; + item1.CreatorId = m_ua2.PrincipalID.ToString(); item1.Owner = UUID.Zero; - + + Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); + string item1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); - tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), null)); + tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), scene.UserAccountService)); tar.Close(); m_iarStream = new MemoryStream(archiveWriteStream.ToArray()); } @@ -385,7 +388,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene("inventory"); SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "meowfood"); UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); -- cgit v1.1 From df860516bf4fa4e4196be4d5fc26db71d98334f4 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Fri, 3 Dec 2010 16:17:50 -0800 Subject: Various bug fixes for appearance handling: more aggressive reset of textures and vparams when appearance is not cached and when wearables change. Send appearance to the viewer with initial data. Cleaned up (and added) debugging. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 99 ++++++++++++++-------- 1 file changed, 63 insertions(+), 36 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index ab1c206..7d6d191 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -115,8 +115,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory #endregion + /// + /// Check for the existence of the baked texture assets. Request a rebake + /// unless checkonly is true. + /// + /// + /// public bool ValidateBakedTextureCache(IClientAPI client) { + return ValidateBakedTextureCache(client, true); + } + + private bool ValidateBakedTextureCache(IClientAPI client, bool checkonly) + { ScenePresence sp = m_scene.GetScenePresence(client.AgentId); if (sp == null) { @@ -131,15 +142,33 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { int idx = AvatarAppearance.BAKE_INDICES[i]; Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; - if (face == null || face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) + + // if there is no texture entry, skip it + if (face == null) continue; + // if the texture is one of the "defaults" then skip it + // this should probably be more intelligent (skirt texture doesnt matter + // if the avatar isnt wearing a skirt) but if any of the main baked + // textures is default then the rest should be as well + if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) + continue; + defonly = false; // found a non-default texture reference if (! CheckBakedTextureAsset(client,face.TextureID,idx)) - return false; + { + // the asset didn't exist if we are only checking, then we found a bad + // one and we're done otherwise, ask for a rebake + if (checkonly) return false; + + m_log.InfoFormat("[AVFACTORY] missing baked texture {0}, request rebake",face.TextureID); + client.SendRebakeAvatarTextures(face.TextureID); + } } + m_log.InfoFormat("[AVFACTORY]: complete texture check for {0}",client.AgentId); + // If we only found default textures, then the appearance is not cached return (defonly ? false : true); } @@ -158,55 +187,43 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return; } - // m_log.WarnFormat("[AVFACTORY]: Start SetAppearance for {0}",client.AgentId); + m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}",client.AgentId); + // TODO: This is probably not necessary any longer, just assume the + // textureEntry set implies that the appearance transaction is complete bool changed = false; // Process the texture entry transactionally, this doesn't guarantee that Appearance is // going to be handled correctly but it does serialize the updates to the appearance lock (m_setAppearanceLock) { + // Process the visual params, this may change height as well + if (visualParams != null) + { + changed = sp.Appearance.SetVisualParams(visualParams); + if (sp.Appearance.AvatarHeight > 0) + sp.SetHeight(sp.Appearance.AvatarHeight); + } + + // Process the baked texture array if (textureEntry != null) { - changed = sp.Appearance.SetTextureEntries(textureEntry); + changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; - // m_log.WarnFormat("[AVFACTORY]: Prepare to check textures for {0}",client.AgentId); + m_log.InfoFormat("[AVFACTORY]: received texture update for {0}",client.AgentId); + Util.FireAndForget(delegate(object o) { ValidateBakedTextureCache(client,false); }); - for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) - { - int idx = AvatarAppearance.BAKE_INDICES[i]; - Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; - if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) - Util.FireAndForget(delegate(object o) { - if (! CheckBakedTextureAsset(client,face.TextureID,idx)) - client.SendRebakeAvatarTextures(face.TextureID); - }); - } + // This appears to be set only in the final stage of the appearance + // update transaction. In theory, we should be able to do an immediate + // appearance send and save here. - m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); + QueueAppearanceSave(client.AgentId); + QueueAppearanceSend(client.AgentId); } - // Process the visual params, this may change height as well - if (visualParams != null) - { - if (sp.Appearance.SetVisualParams(visualParams)) - { - changed = true; - if (sp.Appearance.AvatarHeight > 0) - sp.SetHeight(sp.Appearance.AvatarHeight); - } - } } - - // If something changed in the appearance then queue an appearance save - if (changed) - QueueAppearanceSave(client.AgentId); - - // And always queue up an appearance update to send out - QueueAppearanceSend(client.AgentId); - - // m_log.WarnFormat("[AVFACTORY]: Complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); + // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); } /// @@ -229,6 +246,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory #region UpdateAppearanceTimer + /// + /// Queue up a request to send appearance, makes it possible to + /// accumulate changes without sending out each one separately. + /// public void QueueAppearanceSend(UUID agentid) { // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); @@ -268,6 +289,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Send the appearance to everyone in the scene sp.SendAppearanceToAllOtherAgents(); + + // Send animations back to the avatar as well + sp.Animator.SendAnimPack(); } private void HandleAppearanceSave(UUID agentid) @@ -353,9 +377,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); + // we need to clean out the existing textures + sp.Appearance.ResetAppearance(); + // operate on a copy of the appearance so we don't have to lock anything AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); - + foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) { if (wear.Type < AvatarWearable.MAX_WEARABLES) -- cgit v1.1