diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index f1713a6a39..a7bd398e3d 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -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> 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>(); 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); } /// @@ -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 /// diff --git a/OpenSim/Framework/AvatarWearable.cs b/OpenSim/Framework/AvatarWearable.cs index abf575948b..1733559d96 100644 --- a/OpenSim/Framework/AvatarWearable.cs +++ b/OpenSim/Framework/AvatarWearable.cs @@ -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"); diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index da964e731f..8fcd9a4970 100755 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1107,7 +1107,7 @@ namespace OpenSim.Framework /// The id of the agent associated with the appearance /// /// - 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 cachedTextures); diff --git a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs index 5ad0030ed8..c8eb57dd59 100644 --- a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs +++ b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs @@ -220,12 +220,6 @@ namespace OpenSim.Framework.Tests AvAppearance.VisualParams = VisualParams; - List wearbyte = new List(); - for (int i = 0; i < VisualParams.Length; i++) - { - wearbyte.Add(VisualParams[i]); - } - AvAppearance.SetAppearance(AvAppearance.Texture, (byte[])VisualParams.Clone()); } diff --git a/OpenSim/Framework/VersionInfo.cs b/OpenSim/Framework/VersionInfo.cs index ac1f3a0f05..a1ba2aa5fe 100644 --- a/OpenSim/Framework/VersionInfo.cs +++ b/OpenSim/Framework/VersionInfo.cs @@ -85,8 +85,8 @@ namespace OpenSim /// - this is an older teleport protocol used in OpenSimulator 0.7.5 and before. /// 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; } } diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs index e060f22bf6..f832ff9e43 100644 --- a/OpenSim/Framework/WearableCacheItem.cs +++ b/OpenSim/Framework/WearableCacheItem.cs @@ -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; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f8a563641d..07d96f0ef5 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -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); diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 777d0209ab..2013938f6f 100755 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -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 m_savequeue = new Dictionary(); - private Dictionary m_sendqueue = new Dictionary(); + private ConcurrentDictionary m_savequeue = new ConcurrentDictionary(); + private ConcurrentDictionary m_sendqueue = new ConcurrentDictionary(); + 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(); - IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface(); 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 updatedFaces = new HashSet(); List missing = new List(); - 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(); 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(); + if (cache == null) + return false; + + IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); + lock (m_setAppearanceLock) { - IAssetCache cache = m_scene.RequestModuleInterface(); - IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); - 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 sends = new Dictionary(m_sendqueue); - foreach (KeyValuePair kvp in sends) + UUID id; + long now = DateTime.Now.Ticks; + + foreach (KeyValuePair 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 saves = new Dictionary(m_savequeue); - foreach (KeyValuePair 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 saves = new List(m_savequeue.Count); + foreach (KeyValuePair 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 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 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); + } } /// @@ -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); } } +/* /// /// Respond to the cached textures request from the client /// @@ -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 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); + } } } } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 187df314e4..c55f535f3a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -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) { diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs index 800affef72..8faf4a8a86 100755 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs @@ -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); /// /// Send the appearance of an avatar to others in the scene. /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d53c56285d..9db7633172 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -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) diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 002bfad77d..009c72e935 100755 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -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) { } diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index ded08571a5..1db9ba7499 100755 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -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]; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 798576cd3f..1eb77a7a6a 100755 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -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) { } diff --git a/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs b/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs index b1b3c6fe2c..2f8f151828 100644 --- a/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs +++ b/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs @@ -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()); diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index f5e7771248..18c949e2e9 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -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); diff --git a/OpenSim/Services/Interfaces/IAgentPreferencesService.cs b/OpenSim/Services/Interfaces/IAgentPreferencesService.cs index af923265d8..6d2ce8f56a 100644 --- a/OpenSim/Services/Interfaces/IAgentPreferencesService.cs +++ b/OpenSim/Services/Interfaces/IAgentPreferencesService.cs @@ -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 diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 6cea71f0fc..929fa4a18a 100755 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -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) { } diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index a38c3e873b..b4f8668ee2 100755 Binary files a/bin/OpenMetaverse.Rendering.Meshmerizer.dll and b/bin/OpenMetaverse.Rendering.Meshmerizer.dll differ diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index 40e134fca8..6d806a51d7 100755 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index cbd0e3c29c..ef48b38193 100755 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index e89dbc84a5..a8419a69ad 100755 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ