From be357f8feeb438e3292292d163918a307d69c69a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Aug 2011 01:58:32 +0100 Subject: Fix bug in persisting saved appearances for npcs Assets have to be marked non-local as well as non-temporary to persist. This is now done. Hopefully addresses http://opensimulator.org/mantis/view.php?id=5660 --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 48 ++++++++++++++++---- .../Tests/AvatarFactoryModuleTests.cs | 51 ++++++++++++++++++++++ .../Asset/LocalAssetServiceConnector.cs | 25 ++++++++--- 3 files changed, 111 insertions(+), 13 deletions(-) (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 4627701..f34b6d2 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -257,20 +257,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return true; } - public bool SaveBakedTextures(UUID agentId) + public Dictionary GetBakedTextureFaces(UUID agentId) { ScenePresence sp = m_scene.GetScenePresence(agentId); - if (sp == null || sp.IsChildAgent) - return false; + if (sp == null) + return new Dictionary(); + + return GetBakedTextureFaces(sp); + } + + private Dictionary GetBakedTextureFaces(ScenePresence sp) + { + if (sp.IsChildAgent) + return new Dictionary(); + + Dictionary bakedTextures + = new Dictionary(); AvatarAppearance appearance = sp.Appearance; Primitive.TextureEntryFace[] faceTextures = appearance.Texture.FaceTextures; - m_log.DebugFormat( - "[AV FACTORY]: Permanently saving baked textures for {0} in {1}", - sp.Name, m_scene.RegionInfo.RegionName); - foreach (int i in Enum.GetValues(typeof(BakeType))) { BakeType bakeType = (BakeType)i; @@ -283,7 +290,31 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); - Primitive.TextureEntryFace bakedTextureFace = faceTextures[ftIndex]; + bakedTextures[bakeType] = faceTextures[ftIndex]; + } + + return bakedTextures; + } + + public bool SaveBakedTextures(UUID agentId) + { + ScenePresence sp = m_scene.GetScenePresence(agentId); + + if (sp == null) + return false; + + m_log.DebugFormat( + "[AV FACTORY]: Permanently saving baked textures for {0} in {1}", + sp.Name, m_scene.RegionInfo.RegionName); + + Dictionary bakedTextures = GetBakedTextureFaces(sp); + + if (bakedTextures.Count == 0) + return false; + + foreach (BakeType bakeType in bakedTextures.Keys) + { + Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType]; if (bakedTextureFace == null) { @@ -299,6 +330,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (asset != null) { asset.Temporary = false; + asset.Local = false; m_scene.AssetService.Store(asset); } else diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index b831b31..7b2f14e 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs @@ -26,9 +26,12 @@ */ using System; +using System.Collections.Generic; +using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Asset; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; @@ -65,5 +68,53 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // TODO: Check baked texture Assert.AreEqual(visualParams, sp.Appearance.VisualParams); } + + [Test] + public void TestSaveBakedTextures() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID userId = TestHelpers.ParseTail(0x1); + UUID eyesTextureId = TestHelpers.ParseTail(0x2); + + // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly + // to the AssetService, which will then store temporary and local assets permanently + CoreAssetCache assetCache = new CoreAssetCache(); + + AvatarFactoryModule afm = new AvatarFactoryModule(); + TestScene scene = SceneHelpers.SetupScene(assetCache); + SceneHelpers.SetupSceneModules(scene, afm); + IClientAPI tc = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; + + // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules + AssetBase uploadedAsset; + uploadedAsset = new AssetBase(eyesTextureId, "Baked Texture", (sbyte)AssetType.Texture, userId.ToString()); + uploadedAsset.Data = new byte[] { 2 }; + uploadedAsset.Temporary = true; + uploadedAsset.Local = true; // Local assets aren't persisted, non-local are + scene.AssetService.Store(uploadedAsset); + + byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; + for (byte i = 0; i < visualParams.Length; i++) + visualParams[i] = i; + + Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)); + uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes); + Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); + eyesFace.TextureID = eyesTextureId; + + afm.SetAppearanceFromClient(tc, bakedTextureEntry, visualParams); + afm.SaveBakedTextures(userId); +// Dictionary bakedTextures = afm.GetBakedTextureFaces(userId); + + // We should also inpsect the asset data store layer directly, but this is difficult to get at right now. + assetCache.Clear(); + + AssetBase eyesBake = scene.AssetService.Get(eyesTextureId.ToString()); + Assert.That(eyesBake, Is.Not.Null); + Assert.That(eyesBake.Temporary, Is.False); + Assert.That(eyesBake.Local, Is.False); + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 51d1d59..cc5d061 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -129,15 +129,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset m_Cache = null; } - m_log.InfoFormat("[LOCAL ASSET SERVICES CONNECTOR]: Enabled local assets for region {0}", scene.RegionInfo.RegionName); + m_log.DebugFormat( + "[LOCAL ASSET SERVICES CONNECTOR]: Enabled connector for region {0}", scene.RegionInfo.RegionName); if (m_Cache != null) { - m_log.InfoFormat("[LOCAL ASSET SERVICES CONNECTOR]: Enabled asset caching for region {0}", scene.RegionInfo.RegionName); + m_log.DebugFormat( + "[LOCAL ASSET SERVICES CONNECTOR]: Enabled asset caching for region {0}", + scene.RegionInfo.RegionName); } else { - // Short-circuit directly to storage layer + // Short-circuit directly to storage layer. This ends up storing temporary and local assets. // scene.UnregisterModuleInterface(this); scene.RegisterModuleInterface(m_AssetService); @@ -246,9 +249,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset m_Cache.Cache(asset); if (asset.Temporary || asset.Local) + { +// m_log.DebugFormat( +// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}", +// asset.Name, asset.ID, asset.Temporary, asset.Local); + return asset.ID; - - return m_AssetService.Store(asset); + } + else + { +// m_log.DebugFormat( +// "[LOCAL ASSET SERVICE CONNECTOR]: Passing {0} {1} on to asset service for storage, status Temporary = {2}, Local = {3}", +// asset.Name, asset.ID, asset.Temporary, asset.Local); + + return m_AssetService.Store(asset); + } } public bool UpdateContent(string id, byte[] data) -- cgit v1.1