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
---
.../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 1 -
.../Avatar/AvatarFactory/AvatarFactoryModule.cs | 48 ++++++++++++++++----
.../Tests/AvatarFactoryModuleTests.cs | 51 ++++++++++++++++++++++
.../Asset/LocalAssetServiceConnector.cs | 25 ++++++++---
.../Region/Framework/Interfaces/IAvatarFactory.cs | 17 ++++++++
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 +--
OpenSim/Services/AssetService/AssetService.cs | 9 +++-
OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 35 ++++++++++++---
8 files changed, 168 insertions(+), 24 deletions(-)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index ff889ea..d1ce5df 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -136,7 +136,6 @@ namespace OpenSim.Region.ClientStack.Linden
TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
CAPSFetchInventoryDescendents = m_Scene.HandleFetchInventoryDescendentsCAPS;
GetClient = m_Scene.SceneContents.GetControllingClient;
-
}
///
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)
diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs
index 6817725..4dbddf4 100644
--- a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs
@@ -25,6 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
@@ -39,7 +40,23 @@ namespace OpenSim.Region.Framework.Interfaces
///
bool SendAppearance(UUID agentId);
+ ///
+ /// Return the baked texture ids of the given agent.
+ ///
+ ///
+ /// An empty list if this agent has no baked textures (e.g. because it's a child agent)
+ Dictionary GetBakedTextureFaces(UUID agentId);
+
+ ///
+ /// Save the baked textures for the given agent permanently in the asset database.
+ ///
+ ///
+ /// This is used to preserve apperance textures for NPCs
+ ///
+ ///
+ /// true if a valid agent was found, false otherwise
bool SaveBakedTextures(UUID agentId);
+
bool ValidateBakedTextureCache(IClientAPI client);
void QueueAppearanceSend(UUID agentid);
void QueueAppearanceSave(UUID agentid);
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 4148d4b..4143d44 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1695,9 +1695,9 @@ namespace OpenSim.Region.Framework.Scenes
///
public void MoveToTarget(Vector3 pos, bool noFly)
{
-// m_log.DebugFormat(
-// "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}",
-// Name, pos, m_scene.RegionInfo.RegionName);
+ m_log.DebugFormat(
+ "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}",
+ Name, pos, m_scene.RegionInfo.RegionName);
if (pos.X < 0 || pos.X >= Constants.RegionSize
|| pos.Y < 0 || pos.Y >= Constants.RegionSize
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index d40aa4b..2ea513b 100644
--- a/OpenSim/Services/AssetService/AssetService.cs
+++ b/OpenSim/Services/AssetService/AssetService.cs
@@ -83,7 +83,7 @@ namespace OpenSim.Services.AssetService
if (assetLoaderEnabled)
{
- m_log.InfoFormat("[ASSET]: Loading default asset set from {0}", loaderArgs);
+ m_log.DebugFormat("[ASSET]: Loading default asset set from {0}", loaderArgs);
m_AssetLoader.ForEachDefaultXmlAsset(
loaderArgs,
@@ -100,7 +100,7 @@ namespace OpenSim.Services.AssetService
});
}
- m_log.Info("[ASSET SERVICE]: Local asset service enabled");
+ m_log.Debug("[ASSET SERVICE]: Local asset service enabled");
}
}
}
@@ -180,6 +180,11 @@ namespace OpenSim.Services.AssetService
// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length);
m_Database.StoreAsset(asset);
}
+// else
+// {
+// m_log.DebugFormat(
+// "[ASSET SERVICE]: Not storing asset {0} {1}, bytes {2} as it already exists", asset.Name, asset.FullID, asset.Data.Length);
+// }
return asset.ID;
}
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index 086a725..2cf40d7 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -40,6 +40,7 @@ using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.CoreModules.Avatar.Gods;
+using OpenSim.Region.CoreModules.Asset;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory;
@@ -56,6 +57,11 @@ namespace OpenSim.Tests.Common
///
public class SceneHelpers
{
+ public static TestScene SetupScene()
+ {
+ return SetupScene(null);
+ }
+
///
/// Set up a test scene
///
@@ -63,9 +69,14 @@ namespace OpenSim.Tests.Common
/// Automatically starts service threads, as would the normal runtime.
///
///
- public static TestScene SetupScene()
+ public static TestScene SetupScene(CoreAssetCache cache)
+ {
+ return SetupScene("Unit test region", UUID.Random(), 1000, 1000, cache);
+ }
+
+ public static TestScene SetupScene(string name, UUID id, uint x, uint y)
{
- return SetupScene("Unit test region", UUID.Random(), 1000, 1000);
+ return SetupScene(name, id, x, y, null);
}
///
@@ -78,7 +89,7 @@ namespace OpenSim.Tests.Common
/// Y co-ordinate of the region
/// This should be the same if simulating two scenes within a standalone
///
- public static TestScene SetupScene(string name, UUID id, uint x, uint y)
+ public static TestScene SetupScene(string name, UUID id, uint x, uint y, CoreAssetCache cache)
{
Console.WriteLine("Setting up test scene {0}", name);
@@ -103,7 +114,7 @@ namespace OpenSim.Tests.Common
godsModule.Initialise(testScene, new IniConfigSource());
testScene.AddModule(godsModule.Name, godsModule);
- LocalAssetServicesConnector assetService = StartAssetService(testScene);
+ LocalAssetServicesConnector assetService = StartAssetService(testScene, cache);
StartAuthenticationService(testScene);
LocalInventoryServicesConnector inventoryService = StartInventoryService(testScene);
StartGridService(testScene);
@@ -132,7 +143,7 @@ namespace OpenSim.Tests.Common
return testScene;
}
- private static LocalAssetServicesConnector StartAssetService(Scene testScene)
+ private static LocalAssetServicesConnector StartAssetService(Scene testScene, CoreAssetCache cache)
{
LocalAssetServicesConnector assetService = new LocalAssetServicesConnector();
IConfigSource config = new IniConfigSource();
@@ -145,6 +156,20 @@ namespace OpenSim.Tests.Common
assetService.Initialise(config);
assetService.AddRegion(testScene);
+
+ if (cache != null)
+ {
+ IConfigSource cacheConfig = new IniConfigSource();
+ cacheConfig.AddConfig("Modules");
+ cacheConfig.Configs["Modules"].Set("AssetCaching", "CoreAssetCache");
+ cacheConfig.AddConfig("AssetCache");
+
+ cache.Initialise(cacheConfig);
+ cache.AddRegion(testScene);
+ cache.RegionLoaded(testScene);
+ testScene.AddRegionModule(cache.Name, cache);
+ }
+
assetService.RegionLoaded(testScene);
testScene.AddRegionModule(assetService.Name, assetService);
--
cgit v1.1