mirror of
https://github.com/opensim/opensim.git
synced 2026-08-10 11:33:28 +08:00
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
This commit is contained in:
@@ -257,20 +257,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SaveBakedTextures(UUID agentId)
|
||||
public Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId)
|
||||
{
|
||||
ScenePresence sp = m_scene.GetScenePresence(agentId);
|
||||
|
||||
if (sp == null || sp.IsChildAgent)
|
||||
return false;
|
||||
if (sp == null)
|
||||
return new Dictionary<BakeType, Primitive.TextureEntryFace>();
|
||||
|
||||
return GetBakedTextureFaces(sp);
|
||||
}
|
||||
|
||||
private Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(ScenePresence sp)
|
||||
{
|
||||
if (sp.IsChildAgent)
|
||||
return new Dictionary<BakeType, Primitive.TextureEntryFace>();
|
||||
|
||||
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures
|
||||
= new Dictionary<BakeType, Primitive.TextureEntryFace>();
|
||||
|
||||
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<BakeType, Primitive.TextureEntryFace> 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
|
||||
|
||||
@@ -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<BakeType, Primitive.TextureEntryFace> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<IAssetService>(this);
|
||||
scene.RegisterModuleInterface<IAssetService>(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)
|
||||
|
||||
Reference in New Issue
Block a user