extent supported number of avatar textures/bakes/wearables, tell viewers about it on lludp RegionHandShake; propagate agenthover; block teleports/crossings based on worn wearables and peer version;
parent
6aa369d858
commit
9d6c996570
|
@ -51,27 +51,28 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
// this is viewer capabilities and weared things dependent
|
// this is viewer capabilities and weared things dependent
|
||||||
// should be only used as initial default value ( V1 viewers )
|
// should be only used as initial default value ( V1 viewers )
|
||||||
public readonly static int VISUALPARAM_COUNT = 218;
|
public const int VISUALPARAM_COUNT = 218;
|
||||||
|
|
||||||
// public readonly static int TEXTURE_COUNT = 21
|
// regions and viewer compatibility
|
||||||
// 21 bad, make it be updated as libovm gets update
|
public readonly static int TEXTURE_COUNT = 45;
|
||||||
// also keeping in sync with it
|
public const int TEXTURE_COUNT_PV7 = 26;
|
||||||
public readonly static int TEXTURE_COUNT = Primitive.TextureEntry.MAX_FACES;
|
public const int BAKES_COUNT_PV7 = 6;
|
||||||
|
public const int MAXWEARABLE_PV7 = 16;
|
||||||
|
public const int MAXWEARABLE_LEGACY = 14;
|
||||||
|
|
||||||
public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
|
public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20, 40, 41, 42, 43, 44 };
|
||||||
|
|
||||||
protected int m_serial = 0;
|
protected int m_serial = 0;
|
||||||
protected byte[] m_visualparams;
|
protected byte[] m_visualparams;
|
||||||
protected Primitive.TextureEntry m_texture;
|
protected Primitive.TextureEntry m_texture;
|
||||||
protected AvatarWearable[] m_wearables;
|
protected AvatarWearable[] m_wearables;
|
||||||
protected Dictionary<int, List<AvatarAttachment>> m_attachments;
|
protected Dictionary<int, List<AvatarAttachment>> m_attachments;
|
||||||
protected float m_avatarHeight = 0;
|
protected WearableCacheItem[] m_cacheitems;
|
||||||
protected Vector3 m_avatarSize = new Vector3(0.45f, 0.6f, 1.9f); // sl Z cloud value
|
protected Vector3 m_avatarSize = new Vector3(0.45f, 0.6f, 1.9f); // sl Z cloud value
|
||||||
protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f);
|
protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f);
|
||||||
|
protected float m_avatarHeight = 0;
|
||||||
protected float m_avatarFeetOffset = 0;
|
protected float m_avatarFeetOffset = 0;
|
||||||
protected float m_avatarAnimOffset = 0;
|
protected float m_avatarAnimOffset = 0;
|
||||||
protected WearableCacheItem[] m_cacheitems;
|
|
||||||
protected bool m_cacheItemsDirty = true;
|
|
||||||
|
|
||||||
public virtual int Serial
|
public virtual int Serial
|
||||||
{
|
{
|
||||||
|
@ -128,11 +129,7 @@ namespace OpenSim.Framework
|
||||||
set { m_cacheitems = value; }
|
set { m_cacheitems = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool WearableCacheItemsDirty
|
public virtual float AvatarPreferencesHoverZ { get; set; }
|
||||||
{
|
|
||||||
get { return m_cacheItemsDirty; }
|
|
||||||
set { m_cacheItemsDirty = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public AvatarAppearance()
|
public AvatarAppearance()
|
||||||
{
|
{
|
||||||
|
@ -204,12 +201,14 @@ namespace OpenSim.Framework
|
||||||
SetDefaultParams();
|
SetDefaultParams();
|
||||||
// SetHeight();
|
// SetHeight();
|
||||||
SetSize(new Vector3(0.45f, 0.6f, 1.9f));
|
SetSize(new Vector3(0.45f, 0.6f, 1.9f));
|
||||||
|
AvatarPreferencesHoverZ = 0;
|
||||||
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
|
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_serial = appearance.Serial;
|
m_serial = appearance.Serial;
|
||||||
|
AvatarPreferencesHoverZ = appearance.AvatarPreferencesHoverZ;
|
||||||
|
|
||||||
if (copyWearables && (appearance.Wearables != null))
|
if (copyWearables && (appearance.Wearables != null))
|
||||||
{
|
{
|
||||||
|
@ -228,7 +227,7 @@ namespace OpenSim.Framework
|
||||||
m_texture = null;
|
m_texture = null;
|
||||||
if (appearance.Texture != null)
|
if (appearance.Texture != null)
|
||||||
{
|
{
|
||||||
byte[] tbytes = appearance.Texture.GetBytes();
|
byte[] tbytes = appearance.Texture.GetBakesBytes();
|
||||||
m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length);
|
m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length);
|
||||||
if (copyBaked && appearance.m_cacheitems != null)
|
if (copyBaked && appearance.m_cacheitems != null)
|
||||||
m_cacheitems = (WearableCacheItem[])appearance.m_cacheitems.Clone();
|
m_cacheitems = (WearableCacheItem[])appearance.m_cacheitems.Clone();
|
||||||
|
@ -295,6 +294,7 @@ namespace OpenSim.Framework
|
||||||
m_serial = 0;
|
m_serial = 0;
|
||||||
|
|
||||||
SetDefaultTexture();
|
SetDefaultTexture();
|
||||||
|
AvatarPreferencesHoverZ = 0;
|
||||||
|
|
||||||
//for (int i = 0; i < BAKE_INDICES.Length; i++)
|
//for (int i = 0; i < BAKE_INDICES.Length; i++)
|
||||||
// {
|
// {
|
||||||
|
@ -330,9 +330,6 @@ namespace OpenSim.Framework
|
||||||
protected virtual void SetDefaultTexture()
|
protected virtual void SetDefaultTexture()
|
||||||
{
|
{
|
||||||
m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
|
m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
|
||||||
|
|
||||||
// for (uint i = 0; i < TEXTURE_COUNT; i++)
|
|
||||||
// m_texture.CreateFace(i).TextureID = new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -347,31 +344,31 @@ namespace OpenSim.Framework
|
||||||
if (textureEntry == null)
|
if (textureEntry == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// There are much simpler versions of this copy that could be
|
|
||||||
// made. We determine if any of the textures actually
|
|
||||||
// changed to know if the appearance should be saved later
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
|
Primitive.TextureEntryFace newface;
|
||||||
{
|
Primitive.TextureEntryFace tmpFace;
|
||||||
Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i];
|
|
||||||
Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i];
|
|
||||||
|
|
||||||
if (newface == null)
|
//make sure textureEntry.DefaultTexture is the unused one(DEFAULT_AVATAR_TEXTURE).
|
||||||
|
Primitive.TextureEntry converted = new Primitive.TextureEntry(AppearanceManager.DEFAULT_AVATAR_TEXTURE);
|
||||||
|
for (uint i = 0; i < TEXTURE_COUNT; ++i)
|
||||||
|
{
|
||||||
|
newface = textureEntry.GetFace(i);
|
||||||
|
if (newface.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
||||||
{
|
{
|
||||||
if (oldface == null)
|
tmpFace = converted.GetFace(i);
|
||||||
continue;
|
tmpFace.TextureID = newface.TextureID; // we need a full high level copy, assuming all other parameters are the same.
|
||||||
|
if (m_texture.FaceTextures[i] == null || newface.TextureID != m_texture.FaceTextures[i].TextureID)
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ if (m_texture.FaceTextures[i] == null)
|
||||||
if (oldface != null && oldface.TextureID == newface.TextureID)
|
|
||||||
continue;
|
continue;
|
||||||
|
if(m_texture.FaceTextures[i].TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = true;
|
|
||||||
}
|
}
|
||||||
|
if(changed)
|
||||||
m_texture = textureEntry;
|
m_texture = converted;
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,42 +733,69 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
data["serial"] = OSD.FromInteger(m_serial);
|
data["serial"] = OSD.FromInteger(m_serial);
|
||||||
data["height"] = OSD.FromReal(m_avatarHeight);
|
data["height"] = OSD.FromReal(m_avatarHeight);
|
||||||
|
data["aphz"] = OSD.FromReal(AvatarPreferencesHoverZ);
|
||||||
|
|
||||||
|
if (m_texture == null)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
bool sendPV8 = false;
|
||||||
|
if(ctx != null)
|
||||||
|
sendPV8 = ctx.OutboundVersion >= 0.8;
|
||||||
|
|
||||||
// Wearables
|
// Wearables
|
||||||
//
|
OSDArray wears;
|
||||||
// This will send as many or as few wearables as we have, unless a count
|
int count;
|
||||||
// is given. Used for legacy (pre 0.4) versions.
|
if (ctx == null)
|
||||||
int count = ctx.WearablesCount;
|
count = MAXWEARABLE_LEGACY;
|
||||||
if (ctx.WearablesCount == -1)
|
else
|
||||||
count = m_wearables.Length;
|
|
||||||
OSDArray wears = new OSDArray(count);
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
AvatarWearable dummyWearable = new AvatarWearable();
|
int wbcount = ctx.WearablesCount;
|
||||||
|
if (wbcount == -1)
|
||||||
|
wbcount = m_wearables.Length;
|
||||||
|
|
||||||
if (i < m_wearables.Length)
|
count = wbcount;
|
||||||
wears.Add(m_wearables[i].Pack());
|
if(count > MAXWEARABLE_PV7)
|
||||||
else
|
{
|
||||||
wears.Add(dummyWearable.Pack());
|
count = MAXWEARABLE_PV7;
|
||||||
|
if(sendPV8)
|
||||||
|
{
|
||||||
|
wears = new OSDArray(wbcount - MAXWEARABLE_PV7);
|
||||||
|
for (int i = MAXWEARABLE_PV7; i < wbcount; ++i)
|
||||||
|
wears.Add(m_wearables[i].Pack());
|
||||||
|
|
||||||
|
data["wrbls8"] = wears;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wears = new OSDArray(count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
wears.Add(m_wearables[i].Pack());
|
||||||
data["wearables"] = wears;
|
data["wearables"] = wears;
|
||||||
|
|
||||||
// Avatar Textures
|
// Avatar Textures and preferences hover
|
||||||
OSDArray textures = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
|
OSDArray textures;
|
||||||
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
|
if (sendPV8)
|
||||||
{
|
{
|
||||||
if (m_texture.FaceTextures[i] != null)
|
byte[] te = m_texture.GetBakesBytes();
|
||||||
textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID));
|
data["te8"] = OSD.FromBinary(te);
|
||||||
else
|
}
|
||||||
textures.Add(OSD.FromUUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
|
else
|
||||||
|
{
|
||||||
|
textures = new OSDArray(TEXTURE_COUNT_PV7);
|
||||||
|
for (uint i = 0; i < TEXTURE_COUNT_PV7; i++)
|
||||||
|
textures.Add(OSD.FromUUID(m_texture.GetFace(i).TextureID));
|
||||||
|
data["textures"] = textures;
|
||||||
}
|
}
|
||||||
data["textures"] = textures;
|
|
||||||
|
|
||||||
if (m_cacheitems != null)
|
if (m_cacheitems != null)
|
||||||
{
|
{
|
||||||
OSDArray baked = WearableCacheItem.BakedToOSD(m_cacheitems);
|
OSDArray baked = WearableCacheItem.BakedToOSD(m_cacheitems, 0, BAKES_COUNT_PV7);
|
||||||
if (baked != null)
|
if (baked != null && baked.Count > 0)
|
||||||
data["bakedcache"] = baked;
|
data["bakedcache"] = baked;
|
||||||
|
baked = WearableCacheItem.BakedToOSD(m_cacheitems, BAKES_COUNT_PV7, -1);
|
||||||
|
if (baked != null && baked.Count > 0)
|
||||||
|
data["bc8"] = baked;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visual Parameters
|
// Visual Parameters
|
||||||
|
@ -810,48 +834,88 @@ namespace OpenSim.Framework
|
||||||
OSD tmpOSD;
|
OSD tmpOSD;
|
||||||
if (data.TryGetValue("serial", out tmpOSD))
|
if (data.TryGetValue("serial", out tmpOSD))
|
||||||
m_serial = tmpOSD.AsInteger();
|
m_serial = tmpOSD.AsInteger();
|
||||||
|
if(data.TryGetValue("aphz", out tmpOSD))
|
||||||
|
AvatarPreferencesHoverZ = (float)tmpOSD.AsReal();
|
||||||
if (data.TryGetValue("height", out tmpOSD))
|
if (data.TryGetValue("height", out tmpOSD))
|
||||||
// m_avatarHeight = (float)data["height"].AsReal();
|
SetSize(new Vector3(0.45f, 0.6f, (float)tmpOSD.AsReal()));
|
||||||
SetSize(new Vector3(0.45f,0.6f, (float)tmpOSD.AsReal()));
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Wearables
|
// Wearables
|
||||||
|
OSD tmpOSD8;
|
||||||
|
OSDArray wears8 = null;
|
||||||
|
int wears8Count = 0;
|
||||||
|
|
||||||
|
if (data.TryGetValue("wrbls8", out tmpOSD8) && (tmpOSD8 is OSDArray))
|
||||||
|
{
|
||||||
|
wears8 = (OSDArray)tmpOSD;
|
||||||
|
wears8Count = wears8.Count;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.TryGetValue("wearables", out tmpOSD) && (tmpOSD is OSDArray))
|
if (data.TryGetValue("wearables", out tmpOSD) && (tmpOSD is OSDArray))
|
||||||
{
|
{
|
||||||
OSDArray wears = (OSDArray)tmpOSD;
|
OSDArray wears = (OSDArray)tmpOSD;
|
||||||
m_wearables = new AvatarWearable[wears.Count];
|
m_wearables = new AvatarWearable[wears.Count + wears8Count];
|
||||||
|
|
||||||
for (int i = 0; i < wears.Count; i++)
|
for (int i = 0; i < wears.Count; ++i)
|
||||||
m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
|
m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
|
||||||
|
if (wears8Count > 0)
|
||||||
|
{
|
||||||
|
for (int i = wears.Count; i < wears8Count + wears.Count; ++i)
|
||||||
|
m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.Warn("[AVATAR APPEARANCE]: failed to unpack wearables");
|
m_log.Warn("[AVATAR APPEARANCE]: failed to unpack wearables");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avatar Textures
|
|
||||||
if (data.TryGetValue("textures", out tmpOSD) && (tmpOSD is OSDArray))
|
if (data.TryGetValue("textures", out tmpOSD) && (tmpOSD is OSDArray))
|
||||||
{
|
{
|
||||||
OSDArray textures = (OSDArray)tmpOSD;
|
OSDArray textures = (OSDArray)tmpOSD;
|
||||||
for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT && i < textures.Count; i++)
|
for (int i = 0; i < textures.Count && i < TEXTURE_COUNT_PV7; ++i)
|
||||||
{
|
{
|
||||||
UUID textureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
|
|
||||||
tmpOSD = textures[i];
|
tmpOSD = textures[i];
|
||||||
if (tmpOSD != null)
|
if (tmpOSD != null)
|
||||||
textureID = tmpOSD.AsUUID();
|
m_texture.CreateFace((uint)i).TextureID = tmpOSD.AsUUID();
|
||||||
m_texture.CreateFace((uint)i).TextureID = new UUID(textureID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
if (data.TryGetValue("te8", out tmpOSD))
|
||||||
{
|
{
|
||||||
m_log.Warn("[AVATAR APPEARANCE]: failed to unpack textures");
|
byte[] teb = tmpOSD.AsBinary();
|
||||||
|
Primitive.TextureEntry te = new Primitive.TextureEntry(teb, 0, teb.Length);
|
||||||
|
m_texture = te;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.TryGetValue("bakedcache", out tmpOSD) && (tmpOSD is OSDArray))
|
if (data.TryGetValue("bakedcache", out tmpOSD) && (tmpOSD is OSDArray))
|
||||||
{
|
{
|
||||||
OSDArray bakedOSDArray = (OSDArray)tmpOSD;
|
OSDArray bakedOSDArray = (OSDArray)tmpOSD;
|
||||||
m_cacheitems = WearableCacheItem.BakedFromOSD(bakedOSDArray);
|
m_cacheitems = WearableCacheItem.GetDefaultCacheItem();
|
||||||
|
|
||||||
|
bakedOSDArray = (OSDArray)tmpOSD;
|
||||||
|
foreach (OSDMap item in bakedOSDArray)
|
||||||
|
{
|
||||||
|
int idx = item["textureindex"].AsInteger();
|
||||||
|
if (idx < 0 || idx >= m_cacheitems.Length)
|
||||||
|
continue;
|
||||||
|
m_cacheitems[idx].CacheId = item["cacheid"].AsUUID();
|
||||||
|
m_cacheitems[idx].TextureID = item["textureid"].AsUUID();
|
||||||
|
m_cacheitems[idx].TextureAsset = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.TryGetValue("bc8", out tmpOSD) && (tmpOSD is OSDArray))
|
||||||
|
{
|
||||||
|
bakedOSDArray = (OSDArray)tmpOSD;
|
||||||
|
foreach (OSDMap item in bakedOSDArray)
|
||||||
|
{
|
||||||
|
int idx = item["textureindex"].AsInteger();
|
||||||
|
if (idx < 0 || idx >= m_cacheitems.Length)
|
||||||
|
continue;
|
||||||
|
m_cacheitems[idx].CacheId = item["cacheid"].AsUUID();
|
||||||
|
m_cacheitems[idx].TextureID = item["textureid"].AsUUID();
|
||||||
|
m_cacheitems[idx].TextureAsset = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visual Parameters
|
// Visual Parameters
|
||||||
|
@ -888,6 +952,32 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public bool CanTeleport(float version)
|
||||||
|
{
|
||||||
|
if (version >= 0.8)
|
||||||
|
return true;
|
||||||
|
if (m_wearables.Length <= MAXWEARABLE_PV7)
|
||||||
|
return true;
|
||||||
|
for(int i = MAXWEARABLE_PV7; i < m_wearables.Length; ++i)
|
||||||
|
{
|
||||||
|
if(m_wearables[i].Count > 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// also check baked
|
||||||
|
for(int i = BAKES_COUNT_PV7; i < BAKE_INDICES.Length; i++)
|
||||||
|
{
|
||||||
|
int idx = BAKE_INDICES[i];
|
||||||
|
if (m_texture.FaceTextures[idx] == null)
|
||||||
|
continue;
|
||||||
|
UUID tid = m_texture.FaceTextures[idx].TextureID;
|
||||||
|
if(tid == AppearanceManager.DEFAULT_AVATAR_TEXTURE || tid == UUID.Zero)
|
||||||
|
continue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#region VPElement
|
#region VPElement
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -67,10 +67,14 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
public static readonly int ALPHA = 13;
|
public static readonly int ALPHA = 13;
|
||||||
public static readonly int TATTOO = 14;
|
public static readonly int TATTOO = 14;
|
||||||
|
|
||||||
public static readonly int LEGACY_VERSION_MAX_WEARABLES = 15;
|
public static readonly int LEGACY_VERSION_MAX_WEARABLES = 15;
|
||||||
// public static readonly int PHYSICS = 15;
|
|
||||||
// public static int MAX_WEARABLES = 16;
|
public static readonly int PHYSICS = 15;
|
||||||
|
|
||||||
|
public static int MAX_WEARABLES_PV7 = 16;
|
||||||
|
|
||||||
|
public static readonly int UNIVERSAL = 16;
|
||||||
|
public static int MAX_WEARABLES = 17;
|
||||||
|
|
||||||
|
|
||||||
public static readonly UUID DEFAULT_BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9");
|
public static readonly UUID DEFAULT_BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9");
|
||||||
|
|
|
@ -1107,7 +1107,7 @@ namespace OpenSim.Framework
|
||||||
/// <param name="agentID">The id of the agent associated with the appearance</param>
|
/// <param name="agentID">The id of the agent associated with the appearance</param>
|
||||||
/// <param name="visualParams"></param>
|
/// <param name="visualParams"></param>
|
||||||
/// <param name="textureEntry"></param>
|
/// <param name="textureEntry"></param>
|
||||||
void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry);
|
void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hoverheight);
|
||||||
|
|
||||||
void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures);
|
void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures);
|
||||||
|
|
||||||
|
|
|
@ -220,12 +220,6 @@ namespace OpenSim.Framework.Tests
|
||||||
|
|
||||||
AvAppearance.VisualParams = VisualParams;
|
AvAppearance.VisualParams = VisualParams;
|
||||||
|
|
||||||
List<byte> wearbyte = new List<byte>();
|
|
||||||
for (int i = 0; i < VisualParams.Length; i++)
|
|
||||||
{
|
|
||||||
wearbyte.Add(VisualParams[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
AvAppearance.SetAppearance(AvAppearance.Texture, (byte[])VisualParams.Clone());
|
AvAppearance.SetAppearance(AvAppearance.Texture, (byte[])VisualParams.Clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,8 +85,8 @@ namespace OpenSim
|
||||||
/// - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
|
/// - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public readonly static float SimulationServiceVersionAcceptedMin = 0.3f;
|
public readonly static float SimulationServiceVersionAcceptedMin = 0.3f;
|
||||||
public readonly static float SimulationServiceVersionAcceptedMax = 0.7f;
|
public readonly static float SimulationServiceVersionAcceptedMax = 0.8f;
|
||||||
public readonly static float SimulationServiceVersionSupportedMin = 0.3f;
|
public readonly static float SimulationServiceVersionSupportedMin = 0.3f;
|
||||||
public readonly static float SimulationServiceVersionSupportedMax = 0.7f;
|
public readonly static float SimulationServiceVersionSupportedMax = 0.8f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,31 +128,27 @@ namespace OpenSim.Framework
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems)
|
public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems, int start, int end)
|
||||||
{
|
{
|
||||||
if (pcacheItems.Length < AvatarAppearance.BAKE_INDICES[AvatarAppearance.BAKE_INDICES.Length - 1])
|
OSDArray arr = new OSDArray();
|
||||||
|
if(start < 0)
|
||||||
|
start = 0;
|
||||||
|
if (end < 0 || end > AvatarAppearance.BAKE_INDICES.Length)
|
||||||
|
end = AvatarAppearance.BAKE_INDICES.Length;
|
||||||
|
if (start > end)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
OSDArray arr = new OSDArray();
|
for (int i = start; i < end; i++)
|
||||||
|
|
||||||
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
|
|
||||||
{
|
{
|
||||||
int idx = AvatarAppearance.BAKE_INDICES[i];
|
int idx = AvatarAppearance.BAKE_INDICES[i];
|
||||||
|
if(idx >= pcacheItems.Length)
|
||||||
|
continue;
|
||||||
WearableCacheItem item = pcacheItems[idx];
|
WearableCacheItem item = pcacheItems[idx];
|
||||||
|
|
||||||
OSDMap itemmap = new OSDMap();
|
OSDMap itemmap = new OSDMap();
|
||||||
itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
|
itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
|
||||||
itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
|
itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
|
||||||
itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
|
itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
|
||||||
/*
|
|
||||||
if (item.TextureAsset != null)
|
|
||||||
{
|
|
||||||
itemmap.Add("assetdata", OSD.FromBinary(item.TextureAsset.Data));
|
|
||||||
itemmap.Add("assetcreator", OSD.FromString(item.TextureAsset.CreatorID));
|
|
||||||
itemmap.Add("assetname", OSD.FromString(item.TextureAsset.Name));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
arr.Add(itemmap);
|
arr.Add(itemmap);
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
|
@ -167,22 +163,11 @@ namespace OpenSim.Framework
|
||||||
foreach (OSDMap item in itemarray)
|
foreach (OSDMap item in itemarray)
|
||||||
{
|
{
|
||||||
int idx = item["textureindex"].AsInteger();
|
int idx = item["textureindex"].AsInteger();
|
||||||
if (idx < 0 || idx > pcache.Length)
|
if (idx < 0 || idx >= pcache.Length)
|
||||||
continue;
|
continue;
|
||||||
pcache[idx].CacheId = item["cacheid"].AsUUID();
|
pcache[idx].CacheId = item["cacheid"].AsUUID();
|
||||||
pcache[idx].TextureID = item["textureid"].AsUUID();
|
pcache[idx].TextureID = item["textureid"].AsUUID();
|
||||||
/*
|
pcache[idx].TextureAsset = null;
|
||||||
if (item.ContainsKey("assetdata"))
|
|
||||||
{
|
|
||||||
AssetBase asset = new AssetBase(item["textureid"].AsUUID(), "BakedTexture", (sbyte)AssetType.Texture, UUID.Zero.ToString());
|
|
||||||
asset.Temporary = true;
|
|
||||||
asset.Local = true;
|
|
||||||
asset.Data = item["assetdata"].AsBinary();
|
|
||||||
pcache[idx].TextureAsset = asset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*/
|
|
||||||
pcache[idx].TextureAsset = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pcache;
|
return pcache;
|
||||||
|
|
|
@ -989,11 +989,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
//RegionInfo4 block
|
//RegionInfo4 block
|
||||||
|
|
||||||
//RegionFlagsExtended
|
//RegionFlagsExtended
|
||||||
zc.AddZeros(1); // we dont have this
|
//zc.AddZeros(1); // if we dont have this else
|
||||||
//zc.AddByte(1);
|
zc.AddByte(1);
|
||||||
//zc.AddUInt64(regionFlags); // we have nothing other base flags
|
zc.AddUInt64(regionFlags); // we have nothing other base flags
|
||||||
//RegionProtocols
|
//RegionProtocols
|
||||||
//zc.AddUInt64(0); // bit 0 signals server side texture baking"
|
// bit 0 signals server side texture baking
|
||||||
|
// bit 63 signals more than 6 baked textures support"
|
||||||
|
zc.AddUInt64(1UL << 63);
|
||||||
|
|
||||||
buf.DataLength = zc.Finish();
|
buf.DataLength = zc.Finish();
|
||||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown);
|
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown);
|
||||||
|
@ -4434,7 +4436,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
//0xff, 0xff, 0, 1, 158 // ID 158 (low frequency bigendian) zeroencoded
|
//0xff, 0xff, 0, 1, 158 // ID 158 (low frequency bigendian) zeroencoded
|
||||||
};
|
};
|
||||||
|
|
||||||
public void SendAppearance(UUID targetID, byte[] visualParams, byte[] textureEntry)
|
public void SendAppearance(UUID targetID, byte[] visualParams, byte[] textureEntry, float hover)
|
||||||
{
|
{
|
||||||
// doing post zero encode, because odds of beeing bad are not that low
|
// doing post zero encode, because odds of beeing bad are not that low
|
||||||
UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
|
UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
|
||||||
|
@ -4469,7 +4471,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// no AppearanceData
|
// no AppearanceData
|
||||||
data[pos++] = 0;
|
data[pos++] = 0;
|
||||||
// no AppearanceHover
|
// no AppearanceHover
|
||||||
data[pos++] = 0;
|
data[pos++] = 1;
|
||||||
|
Utils.FloatToBytesSafepos(0, data, pos); pos += 4;
|
||||||
|
Utils.FloatToBytesSafepos(0, data, pos); pos += 4;
|
||||||
|
Utils.FloatToBytesSafepos(hover, data, pos); pos += 4;
|
||||||
|
|
||||||
buf.DataLength = pos;
|
buf.DataLength = pos;
|
||||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true);
|
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -35,6 +36,7 @@ using log4net;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
|
@ -59,8 +61,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
|
private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
|
||||||
private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
|
private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
|
||||||
private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>();
|
private ConcurrentDictionary<UUID,long> m_savequeue = new ConcurrentDictionary<UUID,long>();
|
||||||
private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>();
|
private ConcurrentDictionary<UUID,long> m_sendqueue = new ConcurrentDictionary<UUID,long>();
|
||||||
|
private object m_updatesLock = new object();
|
||||||
|
private int m_updatesbusy = 0;
|
||||||
|
|
||||||
private object m_setAppearanceLock = new object();
|
private object m_setAppearanceLock = new object();
|
||||||
|
|
||||||
|
@ -134,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
client.OnRequestWearables += Client_OnRequestWearables;
|
client.OnRequestWearables += Client_OnRequestWearables;
|
||||||
client.OnSetAppearance += Client_OnSetAppearance;
|
client.OnSetAppearance += Client_OnSetAppearance;
|
||||||
client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
|
client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
|
||||||
client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
|
//client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -232,20 +236,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
sp.SendAppearanceToAllOtherAgents();
|
sp.SendAppearanceToAllOtherAgents();
|
||||||
|
|
||||||
// Send animations back to the avatar as well
|
// Send animations back to the avatar as well
|
||||||
sp.Animator.SendAnimPack();
|
if(sp.Animator != null)
|
||||||
|
sp.Animator.SendAnimPack();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SendAppearance(UUID agentId)
|
public bool SendAppearance(UUID agentId)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
|
|
||||||
|
|
||||||
ScenePresence sp = m_scene.GetScenePresence(agentId);
|
ScenePresence sp = m_scene.GetScenePresence(agentId);
|
||||||
if (sp == null)
|
if (sp == null || sp.IsDeleted)
|
||||||
{
|
|
||||||
// This is expected if the user has gone away.
|
|
||||||
// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
SendAppearance(sp);
|
SendAppearance(sp);
|
||||||
return true;
|
return true;
|
||||||
|
@ -338,11 +337,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
// 10000 ticks per millisecond, 1000 milliseconds per second
|
// 10000 ticks per millisecond, 1000 milliseconds per second
|
||||||
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
|
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
|
||||||
lock (m_sendqueue)
|
m_sendqueue[agentid] = timestamp;
|
||||||
{
|
m_updateTimer.Start();
|
||||||
m_sendqueue[agentid] = timestamp;
|
|
||||||
m_updateTimer.Start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueAppearanceSave(UUID agentid)
|
public void QueueAppearanceSave(UUID agentid)
|
||||||
|
@ -351,11 +347,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
// 10000 ticks per millisecond, 1000 milliseconds per second
|
// 10000 ticks per millisecond, 1000 milliseconds per second
|
||||||
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
|
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
|
||||||
lock (m_savequeue)
|
m_savequeue[agentid] = timestamp;
|
||||||
{
|
m_updateTimer.Start();
|
||||||
m_savequeue[agentid] = timestamp;
|
|
||||||
m_updateTimer.Start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// called on textures update
|
// called on textures update
|
||||||
|
@ -370,106 +363,90 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
// uploaded baked textures will be in assets local cache
|
// uploaded baked textures will be in assets local cache
|
||||||
IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
|
IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
|
||||||
IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
|
|
||||||
|
|
||||||
int validDirtyBakes = 0;
|
int validDirtyBakes = 0;
|
||||||
int hits = 0;
|
int hits = 0;
|
||||||
|
|
||||||
// our main cacheIDs mapper is p.Appearance.WearableCacheItems
|
// our main cacheIDs mapper is p.Appearance.WearableCacheItems
|
||||||
WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
|
bool hadSkirt = false;
|
||||||
|
|
||||||
|
WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
|
||||||
if (wearableCache == null)
|
if (wearableCache == null)
|
||||||
{
|
|
||||||
wearableCache = WearableCacheItem.GetDefaultCacheItem();
|
wearableCache = WearableCacheItem.GetDefaultCacheItem();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hadSkirt = (wearableCache[19].TextureID != UUID.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HashSet<uint> updatedFaces = new HashSet<uint>();
|
||||||
List<UUID> missing = new List<UUID>();
|
List<UUID> missing = new List<UUID>();
|
||||||
|
|
||||||
bool haveSkirt = (wearableCache[19].TextureID != UUID.Zero);
|
|
||||||
bool haveNewSkirt = false;
|
|
||||||
|
|
||||||
// Process received baked textures
|
// Process received baked textures
|
||||||
for (int i = 0; i < cacheItems.Length; i++)
|
for (int i = 0; i < cacheItems.Length; i++)
|
||||||
{
|
{
|
||||||
int idx = (int)cacheItems[i].TextureIndex;
|
uint idx = cacheItems[i].TextureIndex;
|
||||||
|
if(idx >= AvatarAppearance.TEXTURE_COUNT)
|
||||||
|
{
|
||||||
|
hits++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedFaces.Add(idx);
|
||||||
|
|
||||||
|
wearableCache[idx].TextureAsset = null; // just in case
|
||||||
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
|
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
|
||||||
|
|
||||||
// No face
|
if (face == null || face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
||||||
if (face == null)
|
|
||||||
{
|
{
|
||||||
// for some reason viewer is cleaning this
|
|
||||||
if(idx != 19) // skirt is optional
|
|
||||||
{
|
|
||||||
sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
|
|
||||||
sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
|
|
||||||
}
|
|
||||||
wearableCache[idx].CacheId = UUID.Zero;
|
wearableCache[idx].CacheId = UUID.Zero;
|
||||||
wearableCache[idx].TextureID = UUID.Zero;
|
wearableCache[idx].TextureID = UUID.Zero;
|
||||||
wearableCache[idx].TextureAsset = null;
|
if (idx == 19)
|
||||||
|
{
|
||||||
|
hits++;
|
||||||
|
if(hadSkirt)
|
||||||
|
validDirtyBakes++;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cache != null)
|
||||||
|
{
|
||||||
|
AssetBase asb = null;
|
||||||
|
cache.Get(face.TextureID.ToString(), out asb);
|
||||||
|
wearableCache[idx].TextureAsset = asb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wearableCache[idx].TextureAsset != null)
|
||||||
|
{
|
||||||
|
if ( wearableCache[idx].TextureID != face.TextureID ||
|
||||||
|
wearableCache[idx].CacheId != cacheItems[i].CacheId)
|
||||||
|
validDirtyBakes++;
|
||||||
|
|
||||||
|
wearableCache[idx].TextureID = face.TextureID;
|
||||||
|
wearableCache[idx].CacheId = cacheItems[i].CacheId;
|
||||||
|
hits++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
wearableCache[idx].CacheId = UUID.Zero;
|
||||||
{
|
wearableCache[idx].TextureID = UUID.Zero;
|
||||||
wearableCache[idx].CacheId = UUID.Zero;
|
missing.Add(face.TextureID);
|
||||||
wearableCache[idx].TextureID = UUID.Zero;
|
continue;
|
||||||
wearableCache[idx].TextureAsset = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(idx == 19)
|
|
||||||
haveNewSkirt = true;
|
|
||||||
/*
|
|
||||||
if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
|
|
||||||
{
|
|
||||||
if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
|
|
||||||
{
|
|
||||||
wearableCache[idx].CacheId = cacheItems[i].CacheId;
|
|
||||||
validDirtyBakes++;
|
|
||||||
|
|
||||||
//assuming this can only happen if asset is in cache
|
|
||||||
}
|
|
||||||
hits++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
wearableCache[idx].TextureAsset = null;
|
|
||||||
if (cache != null)
|
|
||||||
{
|
|
||||||
AssetBase asb = null;
|
|
||||||
cache.Get(face.TextureID.ToString(), out asb);
|
|
||||||
wearableCache[idx].TextureAsset = asb;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wearableCache[idx].TextureAsset != null)
|
|
||||||
{
|
|
||||||
if ( wearableCache[idx].TextureID != face.TextureID ||
|
|
||||||
wearableCache[idx].CacheId != cacheItems[i].CacheId)
|
|
||||||
validDirtyBakes++;
|
|
||||||
|
|
||||||
wearableCache[idx].TextureID = face.TextureID;
|
|
||||||
wearableCache[idx].CacheId = cacheItems[i].CacheId;
|
|
||||||
hits++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wearableCache[idx].CacheId = UUID.Zero;
|
|
||||||
wearableCache[idx].TextureID = UUID.Zero;
|
|
||||||
wearableCache[idx].TextureAsset = null;
|
|
||||||
missing.Add(face.TextureID);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle optional skirt case
|
// this may be a current fs bug
|
||||||
if(!haveNewSkirt && haveSkirt)
|
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
|
||||||
{
|
{
|
||||||
wearableCache[19].CacheId = UUID.Zero;
|
uint idx = AvatarAppearance.BAKE_INDICES[i];
|
||||||
wearableCache[19].TextureID = UUID.Zero;
|
if(updatedFaces.Contains(idx))
|
||||||
wearableCache[19].TextureAsset = null;
|
continue;
|
||||||
validDirtyBakes++;
|
|
||||||
|
sp.Appearance.Texture.FaceTextures[idx] = null;
|
||||||
|
|
||||||
|
wearableCache[idx].CacheId = UUID.Zero;
|
||||||
|
wearableCache[idx].TextureID = UUID.Zero;
|
||||||
|
wearableCache[idx].TextureAsset = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp.Appearance.WearableCacheItems = wearableCache;
|
sp.Appearance.WearableCacheItems = wearableCache;
|
||||||
|
@ -480,15 +457,18 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
sp.ControllingClient.SendRebakeAvatarTextures(id);
|
sp.ControllingClient.SendRebakeAvatarTextures(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
if (validDirtyBakes > 0 && hits == cacheItems.Length)
|
if (validDirtyBakes > 0 && hits == cacheItems.Length)
|
||||||
{
|
{
|
||||||
// if we got a full set of baked textures save all in BakedTextureModule
|
// if we got a full set of baked textures save all in BakedTextureModule
|
||||||
|
IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
|
||||||
if (m_BakedTextureModule != null)
|
if (m_BakedTextureModule != null)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}",
|
m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}",
|
||||||
hits.ToString(), validDirtyBakes.ToString(), missing.Count);
|
hits.ToString(), validDirtyBakes.ToString(), missing.Count);
|
||||||
|
|
||||||
m_BakedTextureModule.Store(sp.UUID, wearableCache);
|
m_BakedTextureModule.Store(sp.UUID, wearableCache);
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -505,26 +485,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
// sp.Appearance.WearableCacheItems[j].TextureID);
|
// sp.Appearance.WearableCacheItems[j].TextureID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (hits == cacheItems.Length);
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// called when we get a new root avatar
|
// called when we get a new root avatar
|
||||||
public bool ValidateBakedTextureCache(IScenePresence sp)
|
public bool ValidateBakedTextureCache(IScenePresence sp)
|
||||||
{
|
{
|
||||||
int hits = 0;
|
|
||||||
|
|
||||||
if (((ScenePresence)sp).IsNPC)
|
if (((ScenePresence)sp).IsNPC)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
int hits = 0;
|
||||||
|
|
||||||
|
IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
|
||||||
|
if (cache == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
|
||||||
|
|
||||||
lock (m_setAppearanceLock)
|
lock (m_setAppearanceLock)
|
||||||
{
|
{
|
||||||
IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
|
|
||||||
IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
|
|
||||||
WearableCacheItem[] bakedModuleCache = null;
|
|
||||||
|
|
||||||
if (cache == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
|
WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
|
||||||
|
|
||||||
// big debug
|
// big debug
|
||||||
|
@ -566,70 +545,47 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we may have received a full cache
|
|
||||||
// check same coerence and store
|
|
||||||
wearableCacheValid = true;
|
wearableCacheValid = true;
|
||||||
|
Primitive.TextureEntryFace face;
|
||||||
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
|
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
|
||||||
{
|
{
|
||||||
int idx = AvatarAppearance.BAKE_INDICES[i];
|
int idx = AvatarAppearance.BAKE_INDICES[i];
|
||||||
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
|
face = sp.Appearance.Texture.FaceTextures[idx];
|
||||||
if (face != null)
|
|
||||||
|
if(face == null || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
||||||
{
|
{
|
||||||
if (face.TextureID == wearableCache[idx].TextureID &&
|
wearableCache[idx].CacheId = UUID.Zero;
|
||||||
face.TextureID != UUID.Zero)
|
wearableCache[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
|
||||||
{
|
hits++;
|
||||||
if (wearableCache[idx].TextureAsset != null)
|
continue;
|
||||||
{
|
|
||||||
hits++;
|
|
||||||
wearableCache[idx].TextureAsset.Temporary = true;
|
|
||||||
wearableCache[idx].TextureAsset.Local = true;
|
|
||||||
cache.Cache(wearableCache[idx].TextureAsset);
|
|
||||||
wearableCache[idx].TextureAsset = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache.Check((wearableCache[idx].TextureID).ToString()))
|
|
||||||
{
|
|
||||||
hits++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wearableCacheValid = false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
|
if (face.TextureID == wearableCache[idx].TextureID &&
|
||||||
if (wearableCacheValid)
|
face.TextureID != UUID.Zero)
|
||||||
{
|
{
|
||||||
// m_log.Debug("[ValidateBakedCache] have valid local cache");
|
if (cache.Check((wearableCache[idx].TextureID).ToString()))
|
||||||
|
{
|
||||||
|
hits++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wearableCache[idx].CacheId = UUID.Zero;
|
||||||
|
wearableCache[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
|
||||||
|
wearableCacheValid = false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
wearableCache[19].TextureAsset = null; // clear optional skirt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkExternal = false;
|
bool checkExternal = false;
|
||||||
|
|
||||||
if (!wearableCacheValid)
|
if (!wearableCacheValid)
|
||||||
{
|
checkExternal = bakedModule != null;
|
||||||
hits = 0;
|
|
||||||
// only use external bake module on login condition check
|
|
||||||
// ScenePresence ssp = null;
|
|
||||||
// if (sp is ScenePresence)
|
|
||||||
{
|
|
||||||
// ssp = (ScenePresence)sp;
|
|
||||||
// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
|
|
||||||
// bakedModule != null;
|
|
||||||
|
|
||||||
// or do it anytime we dont have the cache
|
|
||||||
checkExternal = bakedModule != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkExternal)
|
if (checkExternal)
|
||||||
{
|
{
|
||||||
|
WearableCacheItem[] bakedModuleCache = null;
|
||||||
bool gotbacked = false;
|
bool gotbacked = false;
|
||||||
|
hits = 0;
|
||||||
|
|
||||||
// m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
|
// m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bakedModuleCache = bakedModule.Get(sp.UUID);
|
bakedModuleCache = bakedModule.Get(sp.UUID);
|
||||||
|
@ -647,8 +603,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
for (int i = 0; i < bakedModuleCache.Length; i++)
|
for (int i = 0; i < bakedModuleCache.Length; i++)
|
||||||
{
|
{
|
||||||
int j = (int)bakedModuleCache[i].TextureIndex;
|
int j = (int)bakedModuleCache[i].TextureIndex;
|
||||||
|
if (j < AvatarAppearance.TEXTURE_COUNT && bakedModuleCache[i].TextureAsset != null)
|
||||||
if (bakedModuleCache[i].TextureAsset != null)
|
|
||||||
{
|
{
|
||||||
wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
|
wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
|
||||||
wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
|
wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
|
||||||
|
@ -658,33 +613,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
cache.Cache(bakedModuleCache[i].TextureAsset);
|
cache.Cache(bakedModuleCache[i].TextureAsset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gotbacked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gotbacked)
|
|
||||||
{
|
|
||||||
// force the ones we got
|
// force the ones we got
|
||||||
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
|
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
|
||||||
{
|
{
|
||||||
int idx = AvatarAppearance.BAKE_INDICES[i];
|
int idx = AvatarAppearance.BAKE_INDICES[i];
|
||||||
if(wearableCache[idx].TextureAsset == null)
|
if (wearableCache[idx].TextureAsset == null)
|
||||||
{
|
{
|
||||||
if(idx == 19)
|
if(idx == 19)
|
||||||
{
|
{
|
||||||
sp.Appearance.Texture.FaceTextures[idx] = null;
|
sp.Appearance.Texture.FaceTextures[idx] = null;
|
||||||
hits++;
|
hits++;
|
||||||
}
|
}
|
||||||
|
else if(sp.Appearance.Texture.FaceTextures[idx] == null ||
|
||||||
|
sp.Appearance.Texture.FaceTextures[idx].TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
||||||
|
hits++;
|
||||||
|
wearableCache[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
|
||||||
|
wearableCache[idx].CacheId = UUID.Zero;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
|
Primitive.TextureEntryFace face = sp.Appearance.Texture.GetFace((uint)idx);
|
||||||
|
|
||||||
if (face == null)
|
|
||||||
{
|
|
||||||
face = sp.Appearance.Texture.CreateFace((uint)idx);
|
|
||||||
sp.Appearance.Texture.FaceTextures[idx] = face;
|
|
||||||
}
|
|
||||||
|
|
||||||
face.TextureID = wearableCache[idx].TextureID;
|
face.TextureID = wearableCache[idx].TextureID;
|
||||||
hits++;
|
hits++;
|
||||||
wearableCache[idx].TextureAsset = null;
|
wearableCache[idx].TextureAsset = null;
|
||||||
|
@ -708,7 +657,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
sp.Appearance.WearableCacheItems[j].TextureID);
|
sp.Appearance.WearableCacheItems[j].TextureID);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
|
return (hits >= AvatarAppearance.BAKE_INDICES.Length); // skirt is optional
|
||||||
}
|
}
|
||||||
|
|
||||||
public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
|
public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
|
||||||
|
@ -776,13 +725,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
foreach (int i in Enum.GetValues(typeof(BakeType)))
|
foreach (int i in Enum.GetValues(typeof(BakeType)))
|
||||||
{
|
{
|
||||||
BakeType bakeType = (BakeType)i;
|
BakeType bakeType = (BakeType)i;
|
||||||
|
if (bakeType == BakeType.NumberOfEntries)
|
||||||
|
break;
|
||||||
|
|
||||||
if (bakeType == BakeType.Unknown)
|
if (bakeType == BakeType.Unknown)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
|
// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
|
||||||
// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
|
// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
|
||||||
|
|
||||||
int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
|
int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
|
||||||
Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture
|
Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture
|
||||||
|
@ -794,90 +745,78 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
|
private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
|
||||||
{
|
{
|
||||||
long now = DateTime.Now.Ticks;
|
if(Monitor.TryEnter(m_updatesLock))
|
||||||
|
|
||||||
lock (m_sendqueue)
|
|
||||||
{
|
{
|
||||||
Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue);
|
UUID id;
|
||||||
foreach (KeyValuePair<UUID, long> kvp in sends)
|
long now = DateTime.Now.Ticks;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<UUID, long> kvp in m_sendqueue)
|
||||||
{
|
{
|
||||||
// We have to load the key and value into local parameters to avoid a race condition if we loop
|
|
||||||
// around and load kvp with a different value before FireAndForget has launched its thread.
|
|
||||||
UUID avatarID = kvp.Key;
|
|
||||||
long sendTime = kvp.Value;
|
long sendTime = kvp.Value;
|
||||||
|
if (sendTime > now)
|
||||||
|
continue;
|
||||||
|
|
||||||
// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
|
id = kvp.Key;
|
||||||
|
m_sendqueue.TryRemove(id, out sendTime);
|
||||||
if (sendTime < now)
|
SendAppearance(id);
|
||||||
{
|
|
||||||
Util.FireAndForget(o => SendAppearance(avatarID), null, "AvatarFactoryModule.SendAppearance");
|
|
||||||
m_sendqueue.Remove(avatarID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
lock (m_savequeue)
|
if(m_updatesbusy == 0)
|
||||||
{
|
|
||||||
Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue);
|
|
||||||
foreach (KeyValuePair<UUID, long> kvp in saves)
|
|
||||||
{
|
{
|
||||||
// We have to load the key and value into local parameters to avoid a race condition if we loop
|
m_updatesbusy = -1;
|
||||||
// around and load kvp with a different value before FireAndForget has launched its thread.
|
List<UUID> saves = new List<UUID>(m_savequeue.Count);
|
||||||
UUID avatarID = kvp.Key;
|
foreach (KeyValuePair<UUID, long> kvp in m_savequeue)
|
||||||
long sendTime = kvp.Value;
|
|
||||||
|
|
||||||
if (sendTime < now)
|
|
||||||
{
|
{
|
||||||
Util.FireAndForget(o => SaveAppearance(avatarID), null, "AvatarFactoryModule.SaveAppearance");
|
long sendTime = kvp.Value;
|
||||||
m_savequeue.Remove(avatarID);
|
if (sendTime > now)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
id = kvp.Key;
|
||||||
|
m_savequeue.TryRemove(id, out sendTime);
|
||||||
|
saves.Add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_updatesbusy = 0;
|
||||||
|
if (saves.Count > 0)
|
||||||
|
{
|
||||||
|
++m_updatesbusy;
|
||||||
|
WorkManager.RunInThreadPool(
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
SaveAppearance(saves);
|
||||||
|
saves = null;
|
||||||
|
--m_updatesbusy;
|
||||||
|
}, null, string.Format("SaveAppearance ({0})", m_scene.Name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must lock both queues here so that QueueAppearanceSave() or *Send() don't m_updateTimer.Start() on
|
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
|
||||||
// another thread inbetween the first count calls and m_updateTimer.Stop() on this thread.
|
m_updateTimer.Stop();
|
||||||
lock (m_sendqueue)
|
|
||||||
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
|
Monitor.Exit(m_updatesLock);
|
||||||
m_updateTimer.Stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveAppearance(UUID agentid)
|
private void SaveAppearance(List<UUID> ids)
|
||||||
{
|
{
|
||||||
// We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
|
|
||||||
// in a culture where decimal points are commas and then reloaded in a culture which just treats them as
|
|
||||||
// number seperators.
|
|
||||||
Culture.SetCurrentCulture();
|
|
||||||
|
|
||||||
ScenePresence sp = m_scene.GetScenePresence(agentid);
|
|
||||||
if (sp == null)
|
|
||||||
{
|
|
||||||
// This is expected if the user has gone away.
|
|
||||||
// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
|
// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
|
||||||
|
|
||||||
// This could take awhile since it needs to pull inventory
|
foreach(UUID id in ids)
|
||||||
// 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
|
{
|
||||||
// assets and item asset id changes to complete.
|
ScenePresence sp = m_scene.GetScenePresence(id);
|
||||||
// I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
|
if(sp == null)
|
||||||
// multiple save requests.
|
continue;
|
||||||
SetAppearanceAssets(sp.UUID, sp.Appearance);
|
// This could take awhile since it needs to pull inventory
|
||||||
|
// 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
|
||||||
|
// assets and item asset id changes to complete.
|
||||||
|
// I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
|
||||||
|
// multiple save requests.
|
||||||
|
|
||||||
// List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
|
SetAppearanceAssets(id, sp.Appearance);
|
||||||
// foreach (AvatarAttachment att in attachments)
|
|
||||||
// {
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[AVFACTORY]: For {0} saving attachment {1} at point {2}",
|
|
||||||
// sp.Name, att.ItemID, att.AttachPoint);
|
|
||||||
// }
|
|
||||||
|
|
||||||
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
|
m_scene.AvatarService.SetAppearance(id, sp.Appearance);
|
||||||
|
//m_scene.EventManager.TriggerAvatarAppearanceChanged(sp);
|
||||||
// Trigger this here because it's the final step in the set/queue/save process for appearance setting.
|
}
|
||||||
// Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes).
|
|
||||||
m_scene.EventManager.TriggerAvatarAppearanceChanged(sp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1231,7 +1170,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
// m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
|
// m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
|
||||||
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
|
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
|
||||||
if (sp != null)
|
if (sp != null)
|
||||||
SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems);
|
SetAppearance(sp, textureEntry, visualParams, avSize, cacheItems);
|
||||||
else
|
else
|
||||||
m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
|
m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
|
||||||
}
|
}
|
||||||
|
@ -1251,9 +1190,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 yet
|
// operate on a copy of the appearance so we don't have to lock anything yet
|
||||||
AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false);
|
AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false);
|
||||||
|
|
||||||
|
@ -1280,15 +1216,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
// often sends AvatarIsWearing and SetAppearance packets at once, and AvatarIsWearing
|
// often sends AvatarIsWearing and SetAppearance packets at once, and AvatarIsWearing
|
||||||
// shouldn't overwrite the changes made in SetAppearance.
|
// shouldn't overwrite the changes made in SetAppearance.
|
||||||
sp.Appearance.Wearables = avatAppearance.Wearables;
|
sp.Appearance.Wearables = avatAppearance.Wearables;
|
||||||
sp.Appearance.Texture = avatAppearance.Texture;
|
|
||||||
|
|
||||||
// We don't need to send the appearance here since the "iswearing" will trigger a new set
|
// 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
|
// of visual param and baked texture changes. When those complete, the new appearance will be sent
|
||||||
|
|
||||||
QueueAppearanceSave(client.AgentId);
|
QueueAppearanceSave(client.AgentId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Respond to the cached textures request from the client
|
/// Respond to the cached textures request from the client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1308,23 +1242,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
if (m_reusetextures)
|
if (m_reusetextures)
|
||||||
{
|
{
|
||||||
// this is the most insanely dumb way to do this... however it seems to
|
|
||||||
// actually work. if the appearance has been reset because wearables have
|
|
||||||
// changed then the texture entries are zero'd out until the bakes are
|
|
||||||
// uploaded. on login, if the textures exist in the cache (eg if you logged
|
|
||||||
// into the simulator recently, then the appearance will pull those and send
|
|
||||||
// them back in the packet and you won't have to rebake. if the textures aren't
|
|
||||||
// in the cache then the intial makeroot() call in scenepresence will zero
|
|
||||||
// them out.
|
|
||||||
//
|
|
||||||
// a better solution (though how much better is an open question) is to
|
|
||||||
// store the hashes in the appearance and compare them. Thats's coming.
|
|
||||||
|
|
||||||
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
|
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
|
||||||
if (face != null)
|
if (face != null)
|
||||||
texture = face.TextureID;
|
texture = face.TextureID;
|
||||||
|
|
||||||
// m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedTextureResponseArg response = new CachedTextureResponseArg();
|
CachedTextureResponseArg response = new CachedTextureResponseArg();
|
||||||
|
@ -1334,21 +1254,16 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
cachedTextureResponse.Add(response);
|
cachedTextureResponse.Add(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
|
|
||||||
// The serial number appears to be used to match requests and responses
|
|
||||||
// in the texture transaction. We just send back the serial number
|
|
||||||
// that was provided in the request. The viewer bumps this for us.
|
|
||||||
client.SendCachedTextureResponse(sp, serial, cachedTextureResponse);
|
client.SendCachedTextureResponse(sp, serial, cachedTextureResponse);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
|
public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
|
||||||
{
|
{
|
||||||
outputAction("For {0} in {1}", sp.Name, m_scene.RegionInfo.RegionName);
|
outputAction("For {0} in {1}", null, sp.Name, m_scene.RegionInfo.RegionName);
|
||||||
outputAction(BAKED_TEXTURES_REPORT_FORMAT, "Bake Type", "UUID");
|
outputAction(BAKED_TEXTURES_REPORT_FORMAT, null, "Bake Type", "UUID");
|
||||||
|
|
||||||
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp.UUID);
|
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp.UUID);
|
||||||
|
|
||||||
|
@ -1362,19 +1277,38 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rawTextureID = bakedTextures[bt].TextureID.ToString();
|
if(bakedTextures[bt].TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
|
||||||
|
rawTextureID = "not set";
|
||||||
if (m_scene.AssetService.Get(rawTextureID) == null)
|
|
||||||
rawTextureID += " (not found)";
|
|
||||||
else
|
else
|
||||||
rawTextureID += " (uploaded)";
|
{
|
||||||
|
rawTextureID = bakedTextures[bt].TextureID.ToString();
|
||||||
|
|
||||||
|
if (m_scene.AssetService.Get(rawTextureID) == null)
|
||||||
|
rawTextureID += " (not found)";
|
||||||
|
else
|
||||||
|
rawTextureID += " (uploaded)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outputAction(BAKED_TEXTURES_REPORT_FORMAT, null, bt, rawTextureID);
|
outputAction(BAKED_TEXTURES_REPORT_FORMAT, null, bt, rawTextureID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
||||||
outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete");
|
outputAction("{0} baked appearance texture is {1}", null, sp.Name, bakedTextureValid ? "OK" : "incomplete");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPreferencesHoverZ(UUID agentId, float val)
|
||||||
|
{
|
||||||
|
ScenePresence sp = m_scene.GetScenePresence(agentId);
|
||||||
|
if (sp == null || sp.IsDeleted || sp.IsNPC || sp.IsInTransit)
|
||||||
|
return;
|
||||||
|
float last = sp.Appearance.AvatarPreferencesHoverZ;
|
||||||
|
if(val != last)
|
||||||
|
{
|
||||||
|
sp.Appearance.AvatarPreferencesHoverZ = val;
|
||||||
|
//sp.SendAppearanceToAgentNF(sp);
|
||||||
|
QueueAppearanceSend(agentId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
|
private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
|
||||||
|
private static readonly string OutfitTPError = "destination region does not support the Outfit you are wearing. Please retry with a simpler one";
|
||||||
|
|
||||||
public const bool WaitForAgentArrivedAtDestinationDefault = true;
|
public const bool WaitForAgentArrivedAtDestinationDefault = true;
|
||||||
|
|
||||||
|
@ -720,6 +721,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sp.Appearance.CanTeleport(ctx.OutboundVersion))
|
||||||
|
{
|
||||||
|
sp.ControllingClient.SendTeleportFailed(OutfitTPError);
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because: {3}",
|
||||||
|
sp.Name, sp.Scene.Name, finalDestination.RegionName, "incompatible wearable");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target
|
// Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target
|
||||||
// simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these
|
// simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these
|
||||||
// as server attempts.
|
// as server attempts.
|
||||||
|
@ -1489,6 +1501,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
|
m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!agent.Appearance.CanTeleport(ctx.OutboundVersion))
|
||||||
|
{
|
||||||
|
reason = OutfitTPError;
|
||||||
|
m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1545,7 +1564,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
failureReason = "Access Denied";
|
failureReason = "Access Denied";
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return neighbourRegion;
|
return neighbourRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1599,9 +1617,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
agent.ControllingClient.SendAlertMessage(failureReason);
|
agent.ControllingClient.SendAlertMessage(failureReason);
|
||||||
return agent;
|
return agent;
|
||||||
}
|
}
|
||||||
|
if (!agent.Appearance.CanTeleport(ctx.OutboundVersion))
|
||||||
|
{
|
||||||
|
if (agent.ControllingClient != null)
|
||||||
|
agent.ControllingClient.SendAlertMessage(OutfitTPError);
|
||||||
|
return agent;
|
||||||
|
}
|
||||||
|
|
||||||
// agent.IsInTransit = true;
|
// agent.IsInTransit = true;
|
||||||
|
|
||||||
CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
|
CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
|
||||||
agent.IsInTransit = false;
|
agent.IsInTransit = false;
|
||||||
return agent;
|
return agent;
|
||||||
|
@ -2601,7 +2624,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
string reason = String.Empty;
|
string reason = String.Empty;
|
||||||
|
|
||||||
EntityTransferContext ctx = new EntityTransferContext();
|
EntityTransferContext ctx = new EntityTransferContext();
|
||||||
bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, agentCircData, (uint)TeleportFlags.Default, ctx, out reason);
|
bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, agentCircData, (uint)TeleportFlags.Default, null, out reason);
|
||||||
|
|
||||||
if (regionAccepted)
|
if (regionAccepted)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
{
|
{
|
||||||
void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems);
|
void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems);
|
||||||
void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems);
|
void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems);
|
||||||
|
void SetPreferencesHoverZ(UUID agentId, float val);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send the appearance of an avatar to others in the scene.
|
/// Send the appearance of an avatar to others in the scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -4358,16 +4358,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void SendAppearanceToAgentNF(ScenePresence avatar)
|
public void SendAppearanceToAgentNF(ScenePresence avatar)
|
||||||
{
|
{
|
||||||
if(avatar.UUID == UUID)
|
avatar.ControllingClient.SendAppearance(UUID, Appearance.VisualParams, Appearance.Texture.GetBakesBytes(), Appearance.AvatarPreferencesHoverZ);
|
||||||
{
|
|
||||||
avatar.ControllingClient.SendAppearance(
|
|
||||||
UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
avatar.ControllingClient.SendAppearance(
|
|
||||||
UUID, Appearance.VisualParams, Appearance.Texture.GetBakesBytes());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAnimPackToAgent(ScenePresence p)
|
public void SendAnimPackToAgent(ScenePresence p)
|
||||||
|
|
|
@ -961,7 +961,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
|
public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hoverheight)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -413,13 +413,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
|
||||||
sb.AppendFormat("Wearables checks for {0}\n\n", sp.Name);
|
sb.AppendFormat("Wearables checks for {0}\n\n", sp.Name);
|
||||||
|
|
||||||
AvatarWearable[] wearables = sp.Appearance.Wearables;
|
AvatarWearable[] wearables = sp.Appearance.Wearables;
|
||||||
if(wearables.Count() == 0)
|
if(wearables.Length == 0)
|
||||||
{
|
{
|
||||||
MainConsole.Instance.Output("avatar has no wearables");
|
MainConsole.Instance.Output("avatar has no wearables");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < wearables.Count(); i++)
|
for (int i = 0; i < wearables.Length; i++)
|
||||||
{
|
{
|
||||||
AvatarWearable aw = wearables[i];
|
AvatarWearable aw = wearables[i];
|
||||||
|
|
||||||
|
@ -477,8 +477,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
|
||||||
cdt.AddColumn("Type", 10);
|
cdt.AddColumn("Type", 10);
|
||||||
cdt.AddColumn("Item UUID", ConsoleDisplayUtil.UuidSize);
|
cdt.AddColumn("Item UUID", ConsoleDisplayUtil.UuidSize);
|
||||||
cdt.AddColumn("Asset UUID", ConsoleDisplayUtil.UuidSize);
|
cdt.AddColumn("Asset UUID", ConsoleDisplayUtil.UuidSize);
|
||||||
|
AvatarWearable[] wearables = sp.Appearance.Wearables;
|
||||||
|
|
||||||
for (int i = (int)WearableType.Shape; i < (int)WearableType.Physics; i++)
|
for (int i = 0; i < wearables.Length; i++)
|
||||||
{
|
{
|
||||||
AvatarWearable aw = sp.Appearance.Wearables[i];
|
AvatarWearable aw = sp.Appearance.Wearables[i];
|
||||||
|
|
||||||
|
|
|
@ -664,7 +664,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
|
public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hover)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ namespace OpenSim.Server.Handlers.AgentPreferences
|
||||||
|
|
||||||
AgentPrefs data = new AgentPrefs(userID);
|
AgentPrefs data = new AgentPrefs(userID);
|
||||||
data.AccessPrefs = request["AccessPrefs"].ToString();
|
data.AccessPrefs = request["AccessPrefs"].ToString();
|
||||||
data.HoverHeight = double.Parse(request["HoverHeight"].ToString());
|
data.HoverHeight = float.Parse(request["HoverHeight"].ToString());
|
||||||
data.Language = request["Language"].ToString();
|
data.Language = request["Language"].ToString();
|
||||||
data.LanguageIsPublic = bool.Parse(request["LanguageIsPublic"].ToString());
|
data.LanguageIsPublic = bool.Parse(request["LanguageIsPublic"].ToString());
|
||||||
data.PermEveryone = int.Parse(request["PermEveryone"].ToString());
|
data.PermEveryone = int.Parse(request["PermEveryone"].ToString());
|
||||||
|
|
|
@ -116,6 +116,8 @@ namespace OpenSim.Services.Connectors.Simulation
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OSDMap args = aCircuit.PackAgentCircuitData(ctx);
|
OSDMap args = aCircuit.PackAgentCircuitData(ctx);
|
||||||
|
if(ctx == null)
|
||||||
|
ctx = new EntityTransferContext();
|
||||||
args["context"] = ctx.Pack();
|
args["context"] = ctx.Pack();
|
||||||
PackData(args, source, aCircuit, destination, flags);
|
PackData(args, source, aCircuit, destination, flags);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace OpenSim.Services.Interfaces
|
||||||
if (kvp.ContainsKey("AccessPrefs"))
|
if (kvp.ContainsKey("AccessPrefs"))
|
||||||
AccessPrefs = kvp["AccessPrefs"];
|
AccessPrefs = kvp["AccessPrefs"];
|
||||||
if (kvp.ContainsKey("HoverHeight"))
|
if (kvp.ContainsKey("HoverHeight"))
|
||||||
HoverHeight = double.Parse(kvp["HoverHeight"]);
|
HoverHeight = float.Parse(kvp["HoverHeight"]);
|
||||||
if (kvp.ContainsKey("Language"))
|
if (kvp.ContainsKey("Language"))
|
||||||
Language = kvp["Language"];
|
Language = kvp["Language"];
|
||||||
if (kvp.ContainsKey("LanguageIsPublic"))
|
if (kvp.ContainsKey("LanguageIsPublic"))
|
||||||
|
@ -65,7 +65,7 @@ namespace OpenSim.Services.Interfaces
|
||||||
if (kvp.ContainsKey("AccessPrefs"))
|
if (kvp.ContainsKey("AccessPrefs"))
|
||||||
AccessPrefs = kvp["AccessPrefs"].ToString();
|
AccessPrefs = kvp["AccessPrefs"].ToString();
|
||||||
if (kvp.ContainsKey("HoverHeight"))
|
if (kvp.ContainsKey("HoverHeight"))
|
||||||
HoverHeight = double.Parse(kvp["HoverHeight"].ToString());
|
HoverHeight = float.Parse(kvp["HoverHeight"].ToString());
|
||||||
if (kvp.ContainsKey("Language"))
|
if (kvp.ContainsKey("Language"))
|
||||||
Language = kvp["Language"].ToString();
|
Language = kvp["Language"].ToString();
|
||||||
if (kvp.ContainsKey("LanguageIsPublic"))
|
if (kvp.ContainsKey("LanguageIsPublic"))
|
||||||
|
@ -95,7 +95,7 @@ namespace OpenSim.Services.Interfaces
|
||||||
public UUID PrincipalID = UUID.Zero;
|
public UUID PrincipalID = UUID.Zero;
|
||||||
public string AccessPrefs = "M";
|
public string AccessPrefs = "M";
|
||||||
//public int GodLevel; // *TODO: Implement GodLevel (Unused by the viewer, afaict - 6/11/2015)
|
//public int GodLevel; // *TODO: Implement GodLevel (Unused by the viewer, afaict - 6/11/2015)
|
||||||
public double HoverHeight = 0.0;
|
public float HoverHeight = 0.0f;
|
||||||
public string Language = "en-us";
|
public string Language = "en-us";
|
||||||
public bool LanguageIsPublic = true;
|
public bool LanguageIsPublic = true;
|
||||||
// DefaultObjectPermMasks
|
// DefaultObjectPermMasks
|
||||||
|
|
|
@ -570,7 +570,7 @@ namespace OpenSim.Tests.Common
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
|
public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hover)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue