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;

0.9.1.0-post-fixes
UbitUmarov 2019-09-11 13:51:43 +01:00
parent 6aa369d858
commit 9d6c996570
22 changed files with 441 additions and 412 deletions

View File

@ -51,27 +51,28 @@ namespace OpenSim.Framework
// this is viewer capabilities and weared things dependent
// 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
// 21 bad, make it be updated as libovm gets update
// also keeping in sync with it
public readonly static int TEXTURE_COUNT = Primitive.TextureEntry.MAX_FACES;
// regions and viewer compatibility
public readonly static int TEXTURE_COUNT = 45;
public const int TEXTURE_COUNT_PV7 = 26;
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 byte[] m_visualparams;
protected Primitive.TextureEntry m_texture;
protected AvatarWearable[] m_wearables;
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_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f);
protected float m_avatarHeight = 0;
protected float m_avatarFeetOffset = 0;
protected float m_avatarAnimOffset = 0;
protected WearableCacheItem[] m_cacheitems;
protected bool m_cacheItemsDirty = true;
public virtual int Serial
{
@ -128,11 +129,7 @@ namespace OpenSim.Framework
set { m_cacheitems = value; }
}
public virtual bool WearableCacheItemsDirty
{
get { return m_cacheItemsDirty; }
set { m_cacheItemsDirty = value; }
}
public virtual float AvatarPreferencesHoverZ { get; set; }
public AvatarAppearance()
{
@ -204,12 +201,14 @@ namespace OpenSim.Framework
SetDefaultParams();
// SetHeight();
SetSize(new Vector3(0.45f, 0.6f, 1.9f));
AvatarPreferencesHoverZ = 0;
m_attachments = new Dictionary<int, List<AvatarAttachment>>();
return;
}
m_serial = appearance.Serial;
AvatarPreferencesHoverZ = appearance.AvatarPreferencesHoverZ;
if (copyWearables && (appearance.Wearables != null))
{
@ -228,7 +227,7 @@ namespace OpenSim.Framework
m_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);
if (copyBaked && appearance.m_cacheitems != null)
m_cacheitems = (WearableCacheItem[])appearance.m_cacheitems.Clone();
@ -295,6 +294,7 @@ namespace OpenSim.Framework
m_serial = 0;
SetDefaultTexture();
AvatarPreferencesHoverZ = 0;
//for (int i = 0; i < BAKE_INDICES.Length; i++)
// {
@ -330,9 +330,6 @@ namespace OpenSim.Framework
protected virtual void SetDefaultTexture()
{
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>
@ -347,31 +344,31 @@ namespace OpenSim.Framework
if (textureEntry == null)
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;
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
{
Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i];
Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i];
Primitive.TextureEntryFace newface;
Primitive.TextureEntryFace tmpFace;
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)
continue;
tmpFace = converted.GetFace(i);
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
{
if (oldface != null && oldface.TextureID == newface.TextureID)
{ if (m_texture.FaceTextures[i] == null)
continue;
if(m_texture.FaceTextures[i].TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
changed = true;
}
changed = true;
}
m_texture = textureEntry;
if(changed)
m_texture = converted;
return changed;
}
@ -736,42 +733,69 @@ namespace OpenSim.Framework
data["serial"] = OSD.FromInteger(m_serial);
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
//
// This will send as many or as few wearables as we have, unless a count
// is given. Used for legacy (pre 0.4) versions.
int count = ctx.WearablesCount;
if (ctx.WearablesCount == -1)
count = m_wearables.Length;
OSDArray wears = new OSDArray(count);
for (int i = 0; i < count; i++)
OSDArray wears;
int count;
if (ctx == null)
count = MAXWEARABLE_LEGACY;
else
{
AvatarWearable dummyWearable = new AvatarWearable();
int wbcount = ctx.WearablesCount;
if (wbcount == -1)
wbcount = m_wearables.Length;
if (i < m_wearables.Length)
wears.Add(m_wearables[i].Pack());
else
wears.Add(dummyWearable.Pack());
count = wbcount;
if(count > MAXWEARABLE_PV7)
{
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;
// Avatar Textures
OSDArray textures = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
// Avatar Textures and preferences hover
OSDArray textures;
if (sendPV8)
{
if (m_texture.FaceTextures[i] != null)
textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID));
else
textures.Add(OSD.FromUUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
byte[] te = m_texture.GetBakesBytes();
data["te8"] = OSD.FromBinary(te);
}
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)
{
OSDArray baked = WearableCacheItem.BakedToOSD(m_cacheitems);
if (baked != null)
OSDArray baked = WearableCacheItem.BakedToOSD(m_cacheitems, 0, BAKES_COUNT_PV7);
if (baked != null && baked.Count > 0)
data["bakedcache"] = baked;
baked = WearableCacheItem.BakedToOSD(m_cacheitems, BAKES_COUNT_PV7, -1);
if (baked != null && baked.Count > 0)
data["bc8"] = baked;
}
// Visual Parameters
@ -810,48 +834,88 @@ namespace OpenSim.Framework
OSD tmpOSD;
if (data.TryGetValue("serial", out tmpOSD))
m_serial = tmpOSD.AsInteger();
if(data.TryGetValue("aphz", out tmpOSD))
AvatarPreferencesHoverZ = (float)tmpOSD.AsReal();
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
{
// 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))
{
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]);
if (wears8Count > 0)
{
for (int i = wears.Count; i < wears8Count + wears.Count; ++i)
m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
}
}
else
{
m_log.Warn("[AVATAR APPEARANCE]: failed to unpack wearables");
}
// Avatar Textures
if (data.TryGetValue("textures", out tmpOSD) && (tmpOSD is OSDArray))
{
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];
if (tmpOSD != null)
textureID = tmpOSD.AsUUID();
m_texture.CreateFace((uint)i).TextureID = new UUID(textureID);
m_texture.CreateFace((uint)i).TextureID = tmpOSD.AsUUID();
}
}
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))
{
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
@ -888,6 +952,32 @@ namespace OpenSim.Framework
#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
/// <summary>

View File

@ -67,10 +67,14 @@ namespace OpenSim.Framework
public static readonly int ALPHA = 13;
public static readonly int TATTOO = 14;
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");

View File

@ -1107,7 +1107,7 @@ namespace OpenSim.Framework
/// <param name="agentID">The id of the agent associated with the appearance</param>
/// <param name="visualParams"></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);

View File

@ -220,12 +220,6 @@ namespace OpenSim.Framework.Tests
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());
}

View File

@ -85,8 +85,8 @@ namespace OpenSim
/// - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
/// </remarks>
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 SimulationServiceVersionSupportedMax = 0.7f;
public readonly static float SimulationServiceVersionSupportedMax = 0.8f;
}
}

View File

@ -128,31 +128,27 @@ namespace OpenSim.Framework
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;
OSDArray arr = new OSDArray();
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
for (int i = start; i < end; i++)
{
int idx = AvatarAppearance.BAKE_INDICES[i];
if(idx >= pcacheItems.Length)
continue;
WearableCacheItem item = pcacheItems[idx];
OSDMap itemmap = new OSDMap();
itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
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);
}
return arr;
@ -167,22 +163,11 @@ namespace OpenSim.Framework
foreach (OSDMap item in itemarray)
{
int idx = item["textureindex"].AsInteger();
if (idx < 0 || idx > pcache.Length)
if (idx < 0 || idx >= pcache.Length)
continue;
pcache[idx].CacheId = item["cacheid"].AsUUID();
pcache[idx].TextureID = item["textureid"].AsUUID();
/*
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;
pcache[idx].TextureAsset = null;
}
}
return pcache;

View File

@ -989,11 +989,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//RegionInfo4 block
//RegionFlagsExtended
zc.AddZeros(1); // we dont have this
//zc.AddByte(1);
//zc.AddUInt64(regionFlags); // we have nothing other base flags
//RegionProtocols
//zc.AddUInt64(0); // bit 0 signals server side texture baking"
//zc.AddZeros(1); // if we dont have this else
zc.AddByte(1);
zc.AddUInt64(regionFlags); // we have nothing other base flags
//RegionProtocols
// bit 0 signals server side texture baking
// bit 63 signals more than 6 baked textures support"
zc.AddUInt64(1UL << 63);
buf.DataLength = zc.Finish();
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
};
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
UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
@ -4469,7 +4471,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// no AppearanceData
data[pos++] = 0;
// 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;
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true);

View File

@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Reflection;
using System.Threading;
using System.Text;
@ -35,6 +36,7 @@ using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
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 System.Timers.Timer m_updateTimer = new System.Timers.Timer();
private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>();
private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>();
private ConcurrentDictionary<UUID,long> m_savequeue = new ConcurrentDictionary<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();
@ -134,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
client.OnRequestWearables += Client_OnRequestWearables;
client.OnSetAppearance += Client_OnSetAppearance;
client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
//client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
}
#endregion
@ -232,20 +236,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
sp.SendAppearanceToAllOtherAgents();
// Send animations back to the avatar as well
sp.Animator.SendAnimPack();
if(sp.Animator != null)
sp.Animator.SendAnimPack();
}
public bool SendAppearance(UUID agentId)
{
// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
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);
if (sp == null || sp.IsDeleted)
return false;
}
SendAppearance(sp);
return true;
@ -338,11 +337,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// 10000 ticks per millisecond, 1000 milliseconds per second
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)
@ -351,11 +347,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// 10000 ticks per millisecond, 1000 milliseconds per second
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
@ -370,106 +363,90 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// uploaded baked textures will be in assets local cache
IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
int validDirtyBakes = 0;
int hits = 0;
// our main cacheIDs mapper is p.Appearance.WearableCacheItems
WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
bool hadSkirt = false;
WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
if (wearableCache == null)
{
wearableCache = WearableCacheItem.GetDefaultCacheItem();
else
{
hadSkirt = (wearableCache[19].TextureID != UUID.Zero);
}
HashSet<uint> updatedFaces = new HashSet<uint>();
List<UUID> missing = new List<UUID>();
bool haveSkirt = (wearableCache[19].TextureID != UUID.Zero);
bool haveNewSkirt = false;
// Process received baked textures
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];
// No face
if (face == null)
if (face == null || face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
{
// 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].TextureID = UUID.Zero;
wearableCache[idx].TextureAsset = null;
if (idx == 19)
{
hits++;
if(hadSkirt)
validDirtyBakes++;
}
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
{
if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
{
wearableCache[idx].CacheId = UUID.Zero;
wearableCache[idx].TextureID = UUID.Zero;
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;
}
wearableCache[idx].CacheId = UUID.Zero;
wearableCache[idx].TextureID = UUID.Zero;
missing.Add(face.TextureID);
continue;
}
}
// handle optional skirt case
if(!haveNewSkirt && haveSkirt)
// this may be a current fs bug
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
{
wearableCache[19].CacheId = UUID.Zero;
wearableCache[19].TextureID = UUID.Zero;
wearableCache[19].TextureAsset = null;
validDirtyBakes++;
uint idx = AvatarAppearance.BAKE_INDICES[i];
if(updatedFaces.Contains(idx))
continue;
sp.Appearance.Texture.FaceTextures[idx] = null;
wearableCache[idx].CacheId = UUID.Zero;
wearableCache[idx].TextureID = UUID.Zero;
wearableCache[idx].TextureAsset = null;
}
sp.Appearance.WearableCacheItems = wearableCache;
@ -480,15 +457,18 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
sp.ControllingClient.SendRebakeAvatarTextures(id);
}
bool changed = false;
if (validDirtyBakes > 0 && hits == cacheItems.Length)
{
// if we got a full set of baked textures save all in BakedTextureModule
IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
if (m_BakedTextureModule != null)
{
m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}",
hits.ToString(), validDirtyBakes.ToString(), missing.Count);
m_BakedTextureModule.Store(sp.UUID, wearableCache);
changed = true;
}
}
else
@ -505,26 +485,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// sp.Appearance.WearableCacheItems[j].TextureID);
}
return (hits == cacheItems.Length);
return changed;
}
// called when we get a new root avatar
public bool ValidateBakedTextureCache(IScenePresence sp)
{
int hits = 0;
if (((ScenePresence)sp).IsNPC)
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)
{
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;
// big debug
@ -566,70 +545,47 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
}
else
{
// we may have received a full cache
// check same coerence and store
wearableCacheValid = true;
Primitive.TextureEntryFace face;
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
{
int idx = AvatarAppearance.BAKE_INDICES[i];
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
if (face != null)
{
if (face.TextureID == wearableCache[idx].TextureID &&
face.TextureID != UUID.Zero)
{
if (wearableCache[idx].TextureAsset != null)
{
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;
}
}
face = sp.Appearance.Texture.FaceTextures[idx];
wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
if (wearableCacheValid)
{
// m_log.Debug("[ValidateBakedCache] have valid local cache");
if(face == null || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
{
wearableCache[idx].CacheId = UUID.Zero;
wearableCache[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
hits++;
continue;
}
if (face.TextureID == wearableCache[idx].TextureID &&
face.TextureID != UUID.Zero)
{
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;
if (!wearableCacheValid)
{
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;
}
}
checkExternal = bakedModule != null;
if (checkExternal)
{
WearableCacheItem[] bakedModuleCache = null;
bool gotbacked = false;
hits = 0;
// m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
// m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
try
{
bakedModuleCache = bakedModule.Get(sp.UUID);
@ -647,8 +603,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
for (int i = 0; i < bakedModuleCache.Length; i++)
{
int j = (int)bakedModuleCache[i].TextureIndex;
if (bakedModuleCache[i].TextureAsset != null)
if (j < AvatarAppearance.TEXTURE_COUNT && bakedModuleCache[i].TextureAsset != null)
{
wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
@ -658,33 +613,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
cache.Cache(bakedModuleCache[i].TextureAsset);
}
}
gotbacked = true;
}
if (gotbacked)
{
// force the ones we got
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
{
int idx = AvatarAppearance.BAKE_INDICES[i];
if(wearableCache[idx].TextureAsset == null)
if (wearableCache[idx].TextureAsset == null)
{
if(idx == 19)
{
sp.Appearance.Texture.FaceTextures[idx] = null;
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;
}
Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
if (face == null)
{
face = sp.Appearance.Texture.CreateFace((uint)idx);
sp.Appearance.Texture.FaceTextures[idx] = face;
}
Primitive.TextureEntryFace face = sp.Appearance.Texture.GetFace((uint)idx);
face.TextureID = wearableCache[idx].TextureID;
hits++;
wearableCache[idx].TextureAsset = null;
@ -708,7 +657,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
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)
@ -776,13 +725,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
foreach (int i in Enum.GetValues(typeof(BakeType)))
{
BakeType bakeType = (BakeType)i;
if (bakeType == BakeType.NumberOfEntries)
break;
if (bakeType == BakeType.Unknown)
continue;
// m_log.DebugFormat(
// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
// m_log.DebugFormat(
// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
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)
{
long now = DateTime.Now.Ticks;
lock (m_sendqueue)
if(Monitor.TryEnter(m_updatesLock))
{
Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue);
foreach (KeyValuePair<UUID, long> kvp in sends)
UUID id;
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;
if (sendTime > now)
continue;
// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
if (sendTime < now)
{
Util.FireAndForget(o => SendAppearance(avatarID), null, "AvatarFactoryModule.SendAppearance");
m_sendqueue.Remove(avatarID);
}
id = kvp.Key;
m_sendqueue.TryRemove(id, out sendTime);
SendAppearance(id);
}
}
lock (m_savequeue)
{
Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue);
foreach (KeyValuePair<UUID, long> kvp in saves)
if(m_updatesbusy == 0)
{
// 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;
if (sendTime < now)
m_updatesbusy = -1;
List<UUID> saves = new List<UUID>(m_savequeue.Count);
foreach (KeyValuePair<UUID, long> kvp in m_savequeue)
{
Util.FireAndForget(o => SaveAppearance(avatarID), null, "AvatarFactoryModule.SaveAppearance");
m_savequeue.Remove(avatarID);
long sendTime = kvp.Value;
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
// another thread inbetween the first count calls and m_updateTimer.Stop() on this thread.
lock (m_sendqueue)
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
m_updateTimer.Stop();
if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
m_updateTimer.Stop();
Monitor.Exit(m_updatesLock);
}
}
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);
// 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.
SetAppearanceAssets(sp.UUID, sp.Appearance);
foreach(UUID id in ids)
{
ScenePresence sp = m_scene.GetScenePresence(id);
if(sp == null)
continue;
// 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();
// foreach (AvatarAttachment att in attachments)
// {
// m_log.DebugFormat(
// "[AVFACTORY]: For {0} saving attachment {1} at point {2}",
// sp.Name, att.ItemID, att.AttachPoint);
// }
SetAppearanceAssets(id, sp.Appearance);
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
// 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);
m_scene.AvatarService.SetAppearance(id, sp.Appearance);
//m_scene.EventManager.TriggerAvatarAppearanceChanged(sp);
}
}
/// <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);
ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
if (sp != null)
SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems);
SetAppearance(sp, textureEntry, visualParams, avSize, cacheItems);
else
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;
}
// 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
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
// shouldn't overwrite the changes made in SetAppearance.
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
// of visual param and baked texture changes. When those complete, the new appearance will be sent
QueueAppearanceSave(client.AgentId);
}
}
/*
/// <summary>
/// Respond to the cached textures request from the client
/// </summary>
@ -1308,23 +1242,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
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];
if (face != null)
texture = face.TextureID;
// m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
}
CachedTextureResponseArg response = new CachedTextureResponseArg();
@ -1334,21 +1254,16 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
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);
}
*/
#endregion
public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
{
outputAction("For {0} in {1}", sp.Name, m_scene.RegionInfo.RegionName);
outputAction(BAKED_TEXTURES_REPORT_FORMAT, "Bake Type", "UUID");
outputAction("For {0} in {1}", null, sp.Name, m_scene.RegionInfo.RegionName);
outputAction(BAKED_TEXTURES_REPORT_FORMAT, null, "Bake Type", "UUID");
Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp.UUID);
@ -1362,19 +1277,38 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
}
else
{
rawTextureID = bakedTextures[bt].TextureID.ToString();
if (m_scene.AssetService.Get(rawTextureID) == null)
rawTextureID += " (not found)";
if(bakedTextures[bt].TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
rawTextureID = "not set";
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);
}
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);
}
}
}
}

View File

@ -53,6 +53,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
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;
@ -720,6 +721,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
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
// simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these
// as server attempts.
@ -1489,6 +1501,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
return false;
}
if (!agent.Appearance.CanTeleport(ctx.OutboundVersion))
{
reason = OutfitTPError;
m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
return false;
}
return true;
}
@ -1545,7 +1564,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
failureReason = "Access Denied";
return null;
}
return neighbourRegion;
}
@ -1599,9 +1617,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.ControllingClient.SendAlertMessage(failureReason);
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);
agent.IsInTransit = false;
return agent;
@ -2601,7 +2624,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
string reason = String.Empty;
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)
{

View File

@ -37,7 +37,7 @@ namespace OpenSim.Region.Framework.Interfaces
{
void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems);
void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems);
void SetPreferencesHoverZ(UUID agentId, float val);
/// <summary>
/// Send the appearance of an avatar to others in the scene.
/// </summary>

View File

@ -4358,16 +4358,7 @@ namespace OpenSim.Region.Framework.Scenes
public void SendAppearanceToAgentNF(ScenePresence avatar)
{
if(avatar.UUID == UUID)
{
avatar.ControllingClient.SendAppearance(
UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
}
else
{
avatar.ControllingClient.SendAppearance(
UUID, Appearance.VisualParams, Appearance.Texture.GetBakesBytes());
}
avatar.ControllingClient.SendAppearance(UUID, Appearance.VisualParams, Appearance.Texture.GetBakesBytes(), Appearance.AvatarPreferencesHoverZ);
}
public void SendAnimPackToAgent(ScenePresence p)

View File

@ -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)
{
}

View File

@ -413,13 +413,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
sb.AppendFormat("Wearables checks for {0}\n\n", sp.Name);
AvatarWearable[] wearables = sp.Appearance.Wearables;
if(wearables.Count() == 0)
if(wearables.Length == 0)
{
MainConsole.Instance.Output("avatar has no wearables");
return;
}
for (int i = 0; i < wearables.Count(); i++)
for (int i = 0; i < wearables.Length; i++)
{
AvatarWearable aw = wearables[i];
@ -477,8 +477,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
cdt.AddColumn("Type", 10);
cdt.AddColumn("Item 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];

View File

@ -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)
{
}

View File

@ -129,7 +129,7 @@ namespace OpenSim.Server.Handlers.AgentPreferences
AgentPrefs data = new AgentPrefs(userID);
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.LanguageIsPublic = bool.Parse(request["LanguageIsPublic"].ToString());
data.PermEveryone = int.Parse(request["PermEveryone"].ToString());

View File

@ -116,6 +116,8 @@ namespace OpenSim.Services.Connectors.Simulation
try
{
OSDMap args = aCircuit.PackAgentCircuitData(ctx);
if(ctx == null)
ctx = new EntityTransferContext();
args["context"] = ctx.Pack();
PackData(args, source, aCircuit, destination, flags);

View File

@ -45,7 +45,7 @@ namespace OpenSim.Services.Interfaces
if (kvp.ContainsKey("AccessPrefs"))
AccessPrefs = kvp["AccessPrefs"];
if (kvp.ContainsKey("HoverHeight"))
HoverHeight = double.Parse(kvp["HoverHeight"]);
HoverHeight = float.Parse(kvp["HoverHeight"]);
if (kvp.ContainsKey("Language"))
Language = kvp["Language"];
if (kvp.ContainsKey("LanguageIsPublic"))
@ -65,7 +65,7 @@ namespace OpenSim.Services.Interfaces
if (kvp.ContainsKey("AccessPrefs"))
AccessPrefs = kvp["AccessPrefs"].ToString();
if (kvp.ContainsKey("HoverHeight"))
HoverHeight = double.Parse(kvp["HoverHeight"].ToString());
HoverHeight = float.Parse(kvp["HoverHeight"].ToString());
if (kvp.ContainsKey("Language"))
Language = kvp["Language"].ToString();
if (kvp.ContainsKey("LanguageIsPublic"))
@ -95,7 +95,7 @@ namespace OpenSim.Services.Interfaces
public UUID PrincipalID = UUID.Zero;
public string AccessPrefs = "M";
//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 bool LanguageIsPublic = true;
// DefaultObjectPermMasks

View File

@ -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.