aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorUbitUmarov2019-09-11 13:51:43 +0100
committerUbitUmarov2019-09-11 13:51:43 +0100
commit9d6c996570377f137f93d16c388746f949b9a841 (patch)
tree11076440a1101266dda5651b5160693e25c7b8d0 /OpenSim
parentdisable AvatarHoverHeight useless and viewer side broken (without SSA) (diff)
downloadopensim-SC-9d6c996570377f137f93d16c388746f949b9a841.zip
opensim-SC-9d6c996570377f137f93d16c388746f949b9a841.tar.gz
opensim-SC-9d6c996570377f137f93d16c388746f949b9a841.tar.bz2
opensim-SC-9d6c996570377f137f93d16c388746f949b9a841.tar.xz
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;
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs230
-rw-r--r--OpenSim/Framework/AvatarWearable.cs10
-rwxr-xr-xOpenSim/Framework/IClientAPI.cs2
-rw-r--r--OpenSim/Framework/Tests/AgentCircuitDataTest.cs6
-rw-r--r--OpenSim/Framework/VersionInfo.cs4
-rw-r--r--OpenSim/Framework/WearableCacheItem.cs39
-rwxr-xr-xOpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs19
-rwxr-xr-xOpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs466
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs31
-rwxr-xr-xOpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs11
-rwxr-xr-xOpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs2
-rwxr-xr-xOpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs7
-rwxr-xr-xOpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs2
-rw-r--r--OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs2
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs2
-rw-r--r--OpenSim/Services/Interfaces/IAgentPreferencesService.cs6
-rwxr-xr-xOpenSim/Tests/Common/Mock/TestClient.cs2
18 files changed, 436 insertions, 407 deletions
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index f1713a6..a7bd398 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -51,27 +51,28 @@ namespace OpenSim.Framework
51 51
52 // this is viewer capabilities and weared things dependent 52 // this is viewer capabilities and weared things dependent
53 // should be only used as initial default value ( V1 viewers ) 53 // should be only used as initial default value ( V1 viewers )
54 public readonly static int VISUALPARAM_COUNT = 218; 54 public const int VISUALPARAM_COUNT = 218;
55 55
56// public readonly static int TEXTURE_COUNT = 21 56 // regions and viewer compatibility
57 // 21 bad, make it be updated as libovm gets update 57 public readonly static int TEXTURE_COUNT = 45;
58 // also keeping in sync with it 58 public const int TEXTURE_COUNT_PV7 = 26;
59 public readonly static int TEXTURE_COUNT = Primitive.TextureEntry.MAX_FACES; 59 public const int BAKES_COUNT_PV7 = 6;
60 public const int MAXWEARABLE_PV7 = 16;
61 public const int MAXWEARABLE_LEGACY = 14;
60 62
61 public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 63 public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20, 40, 41, 42, 43, 44 };
62 64
63 protected int m_serial = 0; 65 protected int m_serial = 0;
64 protected byte[] m_visualparams; 66 protected byte[] m_visualparams;
65 protected Primitive.TextureEntry m_texture; 67 protected Primitive.TextureEntry m_texture;
66 protected AvatarWearable[] m_wearables; 68 protected AvatarWearable[] m_wearables;
67 protected Dictionary<int, List<AvatarAttachment>> m_attachments; 69 protected Dictionary<int, List<AvatarAttachment>> m_attachments;
68 protected float m_avatarHeight = 0; 70 protected WearableCacheItem[] m_cacheitems;
69 protected Vector3 m_avatarSize = new Vector3(0.45f, 0.6f, 1.9f); // sl Z cloud value 71 protected Vector3 m_avatarSize = new Vector3(0.45f, 0.6f, 1.9f); // sl Z cloud value
70 protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f); 72 protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f);
73 protected float m_avatarHeight = 0;
71 protected float m_avatarFeetOffset = 0; 74 protected float m_avatarFeetOffset = 0;
72 protected float m_avatarAnimOffset = 0; 75 protected float m_avatarAnimOffset = 0;
73 protected WearableCacheItem[] m_cacheitems;
74 protected bool m_cacheItemsDirty = true;
75 76
76 public virtual int Serial 77 public virtual int Serial
77 { 78 {
@@ -128,11 +129,7 @@ namespace OpenSim.Framework
128 set { m_cacheitems = value; } 129 set { m_cacheitems = value; }
129 } 130 }
130 131
131 public virtual bool WearableCacheItemsDirty 132 public virtual float AvatarPreferencesHoverZ { get; set; }
132 {
133 get { return m_cacheItemsDirty; }
134 set { m_cacheItemsDirty = value; }
135 }
136 133
137 public AvatarAppearance() 134 public AvatarAppearance()
138 { 135 {
@@ -204,12 +201,14 @@ namespace OpenSim.Framework
204 SetDefaultParams(); 201 SetDefaultParams();
205// SetHeight(); 202// SetHeight();
206 SetSize(new Vector3(0.45f, 0.6f, 1.9f)); 203 SetSize(new Vector3(0.45f, 0.6f, 1.9f));
204 AvatarPreferencesHoverZ = 0;
207 m_attachments = new Dictionary<int, List<AvatarAttachment>>(); 205 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
208 206
209 return; 207 return;
210 } 208 }
211 209
212 m_serial = appearance.Serial; 210 m_serial = appearance.Serial;
211 AvatarPreferencesHoverZ = appearance.AvatarPreferencesHoverZ;
213 212
214 if (copyWearables && (appearance.Wearables != null)) 213 if (copyWearables && (appearance.Wearables != null))
215 { 214 {
@@ -228,7 +227,7 @@ namespace OpenSim.Framework
228 m_texture = null; 227 m_texture = null;
229 if (appearance.Texture != null) 228 if (appearance.Texture != null)
230 { 229 {
231 byte[] tbytes = appearance.Texture.GetBytes(); 230 byte[] tbytes = appearance.Texture.GetBakesBytes();
232 m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length); 231 m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length);
233 if (copyBaked && appearance.m_cacheitems != null) 232 if (copyBaked && appearance.m_cacheitems != null)
234 m_cacheitems = (WearableCacheItem[])appearance.m_cacheitems.Clone(); 233 m_cacheitems = (WearableCacheItem[])appearance.m_cacheitems.Clone();
@@ -295,6 +294,7 @@ namespace OpenSim.Framework
295 m_serial = 0; 294 m_serial = 0;
296 295
297 SetDefaultTexture(); 296 SetDefaultTexture();
297 AvatarPreferencesHoverZ = 0;
298 298
299 //for (int i = 0; i < BAKE_INDICES.Length; i++) 299 //for (int i = 0; i < BAKE_INDICES.Length; i++)
300 // { 300 // {
@@ -330,9 +330,6 @@ namespace OpenSim.Framework
330 protected virtual void SetDefaultTexture() 330 protected virtual void SetDefaultTexture()
331 { 331 {
332 m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE)); 332 m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
333
334 // for (uint i = 0; i < TEXTURE_COUNT; i++)
335 // m_texture.CreateFace(i).TextureID = new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE);
336 } 333 }
337 334
338 /// <summary> 335 /// <summary>
@@ -347,31 +344,31 @@ namespace OpenSim.Framework
347 if (textureEntry == null) 344 if (textureEntry == null)
348 return false; 345 return false;
349 346
350 // There are much simpler versions of this copy that could be
351 // made. We determine if any of the textures actually
352 // changed to know if the appearance should be saved later
353 bool changed = false; 347 bool changed = false;
354 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) 348 Primitive.TextureEntryFace newface;
355 { 349 Primitive.TextureEntryFace tmpFace;
356 Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i];
357 Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i];
358 350
359 if (newface == null) 351 //make sure textureEntry.DefaultTexture is the unused one(DEFAULT_AVATAR_TEXTURE).
352 Primitive.TextureEntry converted = new Primitive.TextureEntry(AppearanceManager.DEFAULT_AVATAR_TEXTURE);
353 for (uint i = 0; i < TEXTURE_COUNT; ++i)
354 {
355 newface = textureEntry.GetFace(i);
356 if (newface.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
360 { 357 {
361 if (oldface == null) 358 tmpFace = converted.GetFace(i);
362 continue; 359 tmpFace.TextureID = newface.TextureID; // we need a full high level copy, assuming all other parameters are the same.
360 if (m_texture.FaceTextures[i] == null || newface.TextureID != m_texture.FaceTextures[i].TextureID)
361 changed = true;
363 } 362 }
364 else 363 else
365 { 364 { if (m_texture.FaceTextures[i] == null)
366 if (oldface != null && oldface.TextureID == newface.TextureID)
367 continue; 365 continue;
366 if(m_texture.FaceTextures[i].TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
367 changed = true;
368 } 368 }
369
370 changed = true;
371 } 369 }
372 370 if(changed)
373 m_texture = textureEntry; 371 m_texture = converted;
374
375 return changed; 372 return changed;
376 } 373 }
377 374
@@ -736,42 +733,69 @@ namespace OpenSim.Framework
736 733
737 data["serial"] = OSD.FromInteger(m_serial); 734 data["serial"] = OSD.FromInteger(m_serial);
738 data["height"] = OSD.FromReal(m_avatarHeight); 735 data["height"] = OSD.FromReal(m_avatarHeight);
736 data["aphz"] = OSD.FromReal(AvatarPreferencesHoverZ);
737
738 if (m_texture == null)
739 return data;
740
741 bool sendPV8 = false;
742 if(ctx != null)
743 sendPV8 = ctx.OutboundVersion >= 0.8;
739 744
740 // Wearables 745 // Wearables
741 // 746 OSDArray wears;
742 // This will send as many or as few wearables as we have, unless a count 747 int count;
743 // is given. Used for legacy (pre 0.4) versions. 748 if (ctx == null)
744 int count = ctx.WearablesCount; 749 count = MAXWEARABLE_LEGACY;
745 if (ctx.WearablesCount == -1) 750 else
746 count = m_wearables.Length;
747 OSDArray wears = new OSDArray(count);
748 for (int i = 0; i < count; i++)
749 { 751 {
750 AvatarWearable dummyWearable = new AvatarWearable(); 752 int wbcount = ctx.WearablesCount;
753 if (wbcount == -1)
754 wbcount = m_wearables.Length;
751 755
752 if (i < m_wearables.Length) 756 count = wbcount;
753 wears.Add(m_wearables[i].Pack()); 757 if(count > MAXWEARABLE_PV7)
754 else 758 {
755 wears.Add(dummyWearable.Pack()); 759 count = MAXWEARABLE_PV7;
760 if(sendPV8)
761 {
762 wears = new OSDArray(wbcount - MAXWEARABLE_PV7);
763 for (int i = MAXWEARABLE_PV7; i < wbcount; ++i)
764 wears.Add(m_wearables[i].Pack());
765
766 data["wrbls8"] = wears;
767 }
768 }
756 } 769 }
770
771 wears = new OSDArray(count);
772 for (int i = 0; i < count; i++)
773 wears.Add(m_wearables[i].Pack());
757 data["wearables"] = wears; 774 data["wearables"] = wears;
758 775
759 // Avatar Textures 776 // Avatar Textures and preferences hover
760 OSDArray textures = new OSDArray(AvatarAppearance.TEXTURE_COUNT); 777 OSDArray textures;
761 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) 778 if (sendPV8)
762 { 779 {
763 if (m_texture.FaceTextures[i] != null) 780 byte[] te = m_texture.GetBakesBytes();
764 textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID)); 781 data["te8"] = OSD.FromBinary(te);
765 else 782 }
766 textures.Add(OSD.FromUUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE)); 783 else
784 {
785 textures = new OSDArray(TEXTURE_COUNT_PV7);
786 for (uint i = 0; i < TEXTURE_COUNT_PV7; i++)
787 textures.Add(OSD.FromUUID(m_texture.GetFace(i).TextureID));
788 data["textures"] = textures;
767 } 789 }
768 data["textures"] = textures;
769 790
770 if (m_cacheitems != null) 791 if (m_cacheitems != null)
771 { 792 {
772 OSDArray baked = WearableCacheItem.BakedToOSD(m_cacheitems); 793 OSDArray baked = WearableCacheItem.BakedToOSD(m_cacheitems, 0, BAKES_COUNT_PV7);
773 if (baked != null) 794 if (baked != null && baked.Count > 0)
774 data["bakedcache"] = baked; 795 data["bakedcache"] = baked;
796 baked = WearableCacheItem.BakedToOSD(m_cacheitems, BAKES_COUNT_PV7, -1);
797 if (baked != null && baked.Count > 0)
798 data["bc8"] = baked;
775 } 799 }
776 800
777 // Visual Parameters 801 // Visual Parameters
@@ -810,48 +834,88 @@ namespace OpenSim.Framework
810 OSD tmpOSD; 834 OSD tmpOSD;
811 if (data.TryGetValue("serial", out tmpOSD)) 835 if (data.TryGetValue("serial", out tmpOSD))
812 m_serial = tmpOSD.AsInteger(); 836 m_serial = tmpOSD.AsInteger();
837 if(data.TryGetValue("aphz", out tmpOSD))
838 AvatarPreferencesHoverZ = (float)tmpOSD.AsReal();
813 if (data.TryGetValue("height", out tmpOSD)) 839 if (data.TryGetValue("height", out tmpOSD))
814// m_avatarHeight = (float)data["height"].AsReal(); 840 SetSize(new Vector3(0.45f, 0.6f, (float)tmpOSD.AsReal()));
815 SetSize(new Vector3(0.45f,0.6f, (float)tmpOSD.AsReal()));
816 841
817 try 842 try
818 { 843 {
819 // Wearables 844 // Wearables
845 OSD tmpOSD8;
846 OSDArray wears8 = null;
847 int wears8Count = 0;
848
849 if (data.TryGetValue("wrbls8", out tmpOSD8) && (tmpOSD8 is OSDArray))
850 {
851 wears8 = (OSDArray)tmpOSD;
852 wears8Count = wears8.Count;
853 }
854
820 if (data.TryGetValue("wearables", out tmpOSD) && (tmpOSD is OSDArray)) 855 if (data.TryGetValue("wearables", out tmpOSD) && (tmpOSD is OSDArray))
821 { 856 {
822 OSDArray wears = (OSDArray)tmpOSD; 857 OSDArray wears = (OSDArray)tmpOSD;
823 m_wearables = new AvatarWearable[wears.Count]; 858 m_wearables = new AvatarWearable[wears.Count + wears8Count];
824 859
825 for (int i = 0; i < wears.Count; i++) 860 for (int i = 0; i < wears.Count; ++i)
826 m_wearables[i] = new AvatarWearable((OSDArray)wears[i]); 861 m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
862 if (wears8Count > 0)
863 {
864 for (int i = wears.Count; i < wears8Count + wears.Count; ++i)
865 m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
866 }
827 } 867 }
828 else 868 else
829 { 869 {
830 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack wearables"); 870 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack wearables");
831 } 871 }
832 872
833 // Avatar Textures
834 if (data.TryGetValue("textures", out tmpOSD) && (tmpOSD is OSDArray)) 873 if (data.TryGetValue("textures", out tmpOSD) && (tmpOSD is OSDArray))
835 { 874 {
836 OSDArray textures = (OSDArray)tmpOSD; 875 OSDArray textures = (OSDArray)tmpOSD;
837 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT && i < textures.Count; i++) 876 for (int i = 0; i < textures.Count && i < TEXTURE_COUNT_PV7; ++i)
838 { 877 {
839 UUID textureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
840 tmpOSD = textures[i]; 878 tmpOSD = textures[i];
841 if (tmpOSD != null) 879 if (tmpOSD != null)
842 textureID = tmpOSD.AsUUID(); 880 m_texture.CreateFace((uint)i).TextureID = tmpOSD.AsUUID();
843 m_texture.CreateFace((uint)i).TextureID = new UUID(textureID);
844 } 881 }
845 } 882 }
846 else 883 if (data.TryGetValue("te8", out tmpOSD))
847 { 884 {
848 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack textures"); 885 byte[] teb = tmpOSD.AsBinary();
886 Primitive.TextureEntry te = new Primitive.TextureEntry(teb, 0, teb.Length);
887 m_texture = te;
849 } 888 }
850 889
851 if (data.TryGetValue("bakedcache", out tmpOSD) && (tmpOSD is OSDArray)) 890 if (data.TryGetValue("bakedcache", out tmpOSD) && (tmpOSD is OSDArray))
852 { 891 {
853 OSDArray bakedOSDArray = (OSDArray)tmpOSD; 892 OSDArray bakedOSDArray = (OSDArray)tmpOSD;
854 m_cacheitems = WearableCacheItem.BakedFromOSD(bakedOSDArray); 893 m_cacheitems = WearableCacheItem.GetDefaultCacheItem();
894
895 bakedOSDArray = (OSDArray)tmpOSD;
896 foreach (OSDMap item in bakedOSDArray)
897 {
898 int idx = item["textureindex"].AsInteger();
899 if (idx < 0 || idx >= m_cacheitems.Length)
900 continue;
901 m_cacheitems[idx].CacheId = item["cacheid"].AsUUID();
902 m_cacheitems[idx].TextureID = item["textureid"].AsUUID();
903 m_cacheitems[idx].TextureAsset = null;
904 }
905
906 if (data.TryGetValue("bc8", out tmpOSD) && (tmpOSD is OSDArray))
907 {
908 bakedOSDArray = (OSDArray)tmpOSD;
909 foreach (OSDMap item in bakedOSDArray)
910 {
911 int idx = item["textureindex"].AsInteger();
912 if (idx < 0 || idx >= m_cacheitems.Length)
913 continue;
914 m_cacheitems[idx].CacheId = item["cacheid"].AsUUID();
915 m_cacheitems[idx].TextureID = item["textureid"].AsUUID();
916 m_cacheitems[idx].TextureAsset = null;
917 }
918 }
855 } 919 }
856 920
857 // Visual Parameters 921 // Visual Parameters
@@ -888,6 +952,32 @@ namespace OpenSim.Framework
888 952
889 #endregion 953 #endregion
890 954
955 public bool CanTeleport(float version)
956 {
957 if (version >= 0.8)
958 return true;
959 if (m_wearables.Length <= MAXWEARABLE_PV7)
960 return true;
961 for(int i = MAXWEARABLE_PV7; i < m_wearables.Length; ++i)
962 {
963 if(m_wearables[i].Count > 0)
964 return false;
965 }
966
967 // also check baked
968 for(int i = BAKES_COUNT_PV7; i < BAKE_INDICES.Length; i++)
969 {
970 int idx = BAKE_INDICES[i];
971 if (m_texture.FaceTextures[idx] == null)
972 continue;
973 UUID tid = m_texture.FaceTextures[idx].TextureID;
974 if(tid == AppearanceManager.DEFAULT_AVATAR_TEXTURE || tid == UUID.Zero)
975 continue;
976 return false;
977 }
978 return true;
979 }
980
891 #region VPElement 981 #region VPElement
892 982
893 /// <summary> 983 /// <summary>
diff --git a/OpenSim/Framework/AvatarWearable.cs b/OpenSim/Framework/AvatarWearable.cs
index abf5759..1733559 100644
--- a/OpenSim/Framework/AvatarWearable.cs
+++ b/OpenSim/Framework/AvatarWearable.cs
@@ -67,10 +67,14 @@ namespace OpenSim.Framework
67 67
68 public static readonly int ALPHA = 13; 68 public static readonly int ALPHA = 13;
69 public static readonly int TATTOO = 14; 69 public static readonly int TATTOO = 14;
70
71 public static readonly int LEGACY_VERSION_MAX_WEARABLES = 15; 70 public static readonly int LEGACY_VERSION_MAX_WEARABLES = 15;
72// public static readonly int PHYSICS = 15; 71
73// public static int MAX_WEARABLES = 16; 72 public static readonly int PHYSICS = 15;
73
74 public static int MAX_WEARABLES_PV7 = 16;
75
76 public static readonly int UNIVERSAL = 16;
77 public static int MAX_WEARABLES = 17;
74 78
75 79
76 public static readonly UUID DEFAULT_BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9"); 80 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 da964e7..8fcd9a4 100755
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1107,7 +1107,7 @@ namespace OpenSim.Framework
1107 /// <param name="agentID">The id of the agent associated with the appearance</param> 1107 /// <param name="agentID">The id of the agent associated with the appearance</param>
1108 /// <param name="visualParams"></param> 1108 /// <param name="visualParams"></param>
1109 /// <param name="textureEntry"></param> 1109 /// <param name="textureEntry"></param>
1110 void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry); 1110 void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hoverheight);
1111 1111
1112 void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures); 1112 void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures);
1113 1113
diff --git a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
index 5ad0030..c8eb57d 100644
--- a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
+++ b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
@@ -220,12 +220,6 @@ namespace OpenSim.Framework.Tests
220 220
221 AvAppearance.VisualParams = VisualParams; 221 AvAppearance.VisualParams = VisualParams;
222 222
223 List<byte> wearbyte = new List<byte>();
224 for (int i = 0; i < VisualParams.Length; i++)
225 {
226 wearbyte.Add(VisualParams[i]);
227 }
228
229 AvAppearance.SetAppearance(AvAppearance.Texture, (byte[])VisualParams.Clone()); 223 AvAppearance.SetAppearance(AvAppearance.Texture, (byte[])VisualParams.Clone());
230 } 224 }
231 225
diff --git a/OpenSim/Framework/VersionInfo.cs b/OpenSim/Framework/VersionInfo.cs
index ac1f3a0..a1ba2aa 100644
--- a/OpenSim/Framework/VersionInfo.cs
+++ b/OpenSim/Framework/VersionInfo.cs
@@ -85,8 +85,8 @@ namespace OpenSim
85 /// - this is an older teleport protocol used in OpenSimulator 0.7.5 and before. 85 /// - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
86 /// </remarks> 86 /// </remarks>
87 public readonly static float SimulationServiceVersionAcceptedMin = 0.3f; 87 public readonly static float SimulationServiceVersionAcceptedMin = 0.3f;
88 public readonly static float SimulationServiceVersionAcceptedMax = 0.7f; 88 public readonly static float SimulationServiceVersionAcceptedMax = 0.8f;
89 public readonly static float SimulationServiceVersionSupportedMin = 0.3f; 89 public readonly static float SimulationServiceVersionSupportedMin = 0.3f;
90 public readonly static float SimulationServiceVersionSupportedMax = 0.7f; 90 public readonly static float SimulationServiceVersionSupportedMax = 0.8f;
91 } 91 }
92} 92}
diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs
index e060f22..f832ff9 100644
--- a/OpenSim/Framework/WearableCacheItem.cs
+++ b/OpenSim/Framework/WearableCacheItem.cs
@@ -128,31 +128,27 @@ namespace OpenSim.Framework
128 return arr; 128 return arr;
129 } 129 }
130 130
131 public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems) 131 public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems, int start, int end)
132 { 132 {
133 if (pcacheItems.Length < AvatarAppearance.BAKE_INDICES[AvatarAppearance.BAKE_INDICES.Length - 1])
134 return null;
135
136 OSDArray arr = new OSDArray(); 133 OSDArray arr = new OSDArray();
134 if(start < 0)
135 start = 0;
136 if (end < 0 || end > AvatarAppearance.BAKE_INDICES.Length)
137 end = AvatarAppearance.BAKE_INDICES.Length;
138 if (start > end)
139 return null;
137 140
138 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 141 for (int i = start; i < end; i++)
139 { 142 {
140 int idx = AvatarAppearance.BAKE_INDICES[i]; 143 int idx = AvatarAppearance.BAKE_INDICES[i];
141 144 if(idx >= pcacheItems.Length)
145 continue;
142 WearableCacheItem item = pcacheItems[idx]; 146 WearableCacheItem item = pcacheItems[idx];
143 147
144 OSDMap itemmap = new OSDMap(); 148 OSDMap itemmap = new OSDMap();
145 itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex)); 149 itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
146 itemmap.Add("cacheid", OSD.FromUUID(item.CacheId)); 150 itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
147 itemmap.Add("textureid", OSD.FromUUID(item.TextureID)); 151 itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
148/*
149 if (item.TextureAsset != null)
150 {
151 itemmap.Add("assetdata", OSD.FromBinary(item.TextureAsset.Data));
152 itemmap.Add("assetcreator", OSD.FromString(item.TextureAsset.CreatorID));
153 itemmap.Add("assetname", OSD.FromString(item.TextureAsset.Name));
154 }
155 */
156 arr.Add(itemmap); 152 arr.Add(itemmap);
157 } 153 }
158 return arr; 154 return arr;
@@ -167,22 +163,11 @@ namespace OpenSim.Framework
167 foreach (OSDMap item in itemarray) 163 foreach (OSDMap item in itemarray)
168 { 164 {
169 int idx = item["textureindex"].AsInteger(); 165 int idx = item["textureindex"].AsInteger();
170 if (idx < 0 || idx > pcache.Length) 166 if (idx < 0 || idx >= pcache.Length)
171 continue; 167 continue;
172 pcache[idx].CacheId = item["cacheid"].AsUUID(); 168 pcache[idx].CacheId = item["cacheid"].AsUUID();
173 pcache[idx].TextureID = item["textureid"].AsUUID(); 169 pcache[idx].TextureID = item["textureid"].AsUUID();
174/* 170 pcache[idx].TextureAsset = null;
175 if (item.ContainsKey("assetdata"))
176 {
177 AssetBase asset = new AssetBase(item["textureid"].AsUUID(), "BakedTexture", (sbyte)AssetType.Texture, UUID.Zero.ToString());
178 asset.Temporary = true;
179 asset.Local = true;
180 asset.Data = item["assetdata"].AsBinary();
181 pcache[idx].TextureAsset = asset;
182 }
183 else
184 */
185 pcache[idx].TextureAsset = null;
186 } 171 }
187 } 172 }
188 return pcache; 173 return pcache;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index f8a5636..07d96f0 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
989 //RegionInfo4 block 989 //RegionInfo4 block
990 990
991 //RegionFlagsExtended 991 //RegionFlagsExtended
992 zc.AddZeros(1); // we dont have this 992 //zc.AddZeros(1); // if we dont have this else
993 //zc.AddByte(1); 993 zc.AddByte(1);
994 //zc.AddUInt64(regionFlags); // we have nothing other base flags 994 zc.AddUInt64(regionFlags); // we have nothing other base flags
995 //RegionProtocols 995 //RegionProtocols
996 //zc.AddUInt64(0); // bit 0 signals server side texture baking" 996 // bit 0 signals server side texture baking
997 // bit 63 signals more than 6 baked textures support"
998 zc.AddUInt64(1UL << 63);
997 999
998 buf.DataLength = zc.Finish(); 1000 buf.DataLength = zc.Finish();
999 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown); 1001 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown);
@@ -4434,7 +4436,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4434 //0xff, 0xff, 0, 1, 158 // ID 158 (low frequency bigendian) zeroencoded 4436 //0xff, 0xff, 0, 1, 158 // ID 158 (low frequency bigendian) zeroencoded
4435 }; 4437 };
4436 4438
4437 public void SendAppearance(UUID targetID, byte[] visualParams, byte[] textureEntry) 4439 public void SendAppearance(UUID targetID, byte[] visualParams, byte[] textureEntry, float hover)
4438 { 4440 {
4439 // doing post zero encode, because odds of beeing bad are not that low 4441 // doing post zero encode, because odds of beeing bad are not that low
4440 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); 4442 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
@@ -4469,7 +4471,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4469 // no AppearanceData 4471 // no AppearanceData
4470 data[pos++] = 0; 4472 data[pos++] = 0;
4471 // no AppearanceHover 4473 // no AppearanceHover
4472 data[pos++] = 0; 4474 data[pos++] = 1;
4475 Utils.FloatToBytesSafepos(0, data, pos); pos += 4;
4476 Utils.FloatToBytesSafepos(0, data, pos); pos += 4;
4477 Utils.FloatToBytesSafepos(hover, data, pos); pos += 4;
4473 4478
4474 buf.DataLength = pos; 4479 buf.DataLength = pos;
4475 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true); 4480 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 777d020..2013938 100755
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Concurrent;
30using System.Reflection; 31using System.Reflection;
31using System.Threading; 32using System.Threading;
32using System.Text; 33using System.Text;
@@ -35,6 +36,7 @@ using log4net;
35using Nini.Config; 36using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Monitoring;
38using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
@@ -59,8 +61,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
59 61
60 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates 62 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
61 private System.Timers.Timer m_updateTimer = new System.Timers.Timer(); 63 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
62 private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>(); 64 private ConcurrentDictionary<UUID,long> m_savequeue = new ConcurrentDictionary<UUID,long>();
63 private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>(); 65 private ConcurrentDictionary<UUID,long> m_sendqueue = new ConcurrentDictionary<UUID,long>();
66 private object m_updatesLock = new object();
67 private int m_updatesbusy = 0;
64 68
65 private object m_setAppearanceLock = new object(); 69 private object m_setAppearanceLock = new object();
66 70
@@ -134,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
134 client.OnRequestWearables += Client_OnRequestWearables; 138 client.OnRequestWearables += Client_OnRequestWearables;
135 client.OnSetAppearance += Client_OnSetAppearance; 139 client.OnSetAppearance += Client_OnSetAppearance;
136 client.OnAvatarNowWearing += Client_OnAvatarNowWearing; 140 client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
137 client.OnCachedTextureRequest += Client_OnCachedTextureRequest; 141 //client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
138 } 142 }
139 143
140 #endregion 144 #endregion
@@ -232,20 +236,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
232 sp.SendAppearanceToAllOtherAgents(); 236 sp.SendAppearanceToAllOtherAgents();
233 237
234 // Send animations back to the avatar as well 238 // Send animations back to the avatar as well
235 sp.Animator.SendAnimPack(); 239 if(sp.Animator != null)
240 sp.Animator.SendAnimPack();
236 } 241 }
237 242
238 public bool SendAppearance(UUID agentId) 243 public bool SendAppearance(UUID agentId)
239 { 244 {
240// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
241
242 ScenePresence sp = m_scene.GetScenePresence(agentId); 245 ScenePresence sp = m_scene.GetScenePresence(agentId);
243 if (sp == null) 246 if (sp == null || sp.IsDeleted)
244 {
245 // This is expected if the user has gone away.
246// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
247 return false; 247 return false;
248 }
249 248
250 SendAppearance(sp); 249 SendAppearance(sp);
251 return true; 250 return true;
@@ -338,11 +337,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
338 337
339 // 10000 ticks per millisecond, 1000 milliseconds per second 338 // 10000 ticks per millisecond, 1000 milliseconds per second
340 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); 339 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
341 lock (m_sendqueue) 340 m_sendqueue[agentid] = timestamp;
342 { 341 m_updateTimer.Start();
343 m_sendqueue[agentid] = timestamp;
344 m_updateTimer.Start();
345 }
346 } 342 }
347 343
348 public void QueueAppearanceSave(UUID agentid) 344 public void QueueAppearanceSave(UUID agentid)
@@ -351,11 +347,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
351 347
352 // 10000 ticks per millisecond, 1000 milliseconds per second 348 // 10000 ticks per millisecond, 1000 milliseconds per second
353 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); 349 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
354 lock (m_savequeue) 350 m_savequeue[agentid] = timestamp;
355 { 351 m_updateTimer.Start();
356 m_savequeue[agentid] = timestamp;
357 m_updateTimer.Start();
358 }
359 } 352 }
360 353
361 // called on textures update 354 // called on textures update
@@ -370,106 +363,90 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
370 363
371 // uploaded baked textures will be in assets local cache 364 // uploaded baked textures will be in assets local cache
372 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>(); 365 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
373 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
374 366
375 int validDirtyBakes = 0; 367 int validDirtyBakes = 0;
376 int hits = 0; 368 int hits = 0;
377 369
378 // our main cacheIDs mapper is p.Appearance.WearableCacheItems 370 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
379 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems; 371 bool hadSkirt = false;
380 372
373 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
381 if (wearableCache == null) 374 if (wearableCache == null)
382 {
383 wearableCache = WearableCacheItem.GetDefaultCacheItem(); 375 wearableCache = WearableCacheItem.GetDefaultCacheItem();
376 else
377 {
378 hadSkirt = (wearableCache[19].TextureID != UUID.Zero);
384 } 379 }
385 380
381 HashSet<uint> updatedFaces = new HashSet<uint>();
386 List<UUID> missing = new List<UUID>(); 382 List<UUID> missing = new List<UUID>();
387 383
388 bool haveSkirt = (wearableCache[19].TextureID != UUID.Zero);
389 bool haveNewSkirt = false;
390
391 // Process received baked textures 384 // Process received baked textures
392 for (int i = 0; i < cacheItems.Length; i++) 385 for (int i = 0; i < cacheItems.Length; i++)
393 { 386 {
394 int idx = (int)cacheItems[i].TextureIndex; 387 uint idx = cacheItems[i].TextureIndex;
388 if(idx >= AvatarAppearance.TEXTURE_COUNT)
389 {
390 hits++;
391 continue;
392 }
393
394 updatedFaces.Add(idx);
395
396 wearableCache[idx].TextureAsset = null; // just in case
395 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; 397 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
396 398
397 // No face 399 if (face == null || face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
398 if (face == null)
399 { 400 {
400 // for some reason viewer is cleaning this
401 if(idx != 19) // skirt is optional
402 {
403 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
404 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
405 }
406 wearableCache[idx].CacheId = UUID.Zero; 401 wearableCache[idx].CacheId = UUID.Zero;
407 wearableCache[idx].TextureID = UUID.Zero; 402 wearableCache[idx].TextureID = UUID.Zero;
408 wearableCache[idx].TextureAsset = null; 403 if (idx == 19)
409 continue;
410 }
411 else
412 {
413 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
414 {
415 wearableCache[idx].CacheId = UUID.Zero;
416 wearableCache[idx].TextureID = UUID.Zero;
417 wearableCache[idx].TextureAsset = null;
418 continue;
419 }
420
421 if(idx == 19)
422 haveNewSkirt = true;
423/*
424 if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
425 { 404 {
426 if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
427 {
428 wearableCache[idx].CacheId = cacheItems[i].CacheId;
429 validDirtyBakes++;
430
431 //assuming this can only happen if asset is in cache
432 }
433 hits++; 405 hits++;
434 continue; 406 if(hadSkirt)
435 } 407 validDirtyBakes++;
436*/
437 wearableCache[idx].TextureAsset = null;
438 if (cache != null)
439 {
440 AssetBase asb = null;
441 cache.Get(face.TextureID.ToString(), out asb);
442 wearableCache[idx].TextureAsset = asb;
443 } 408 }
409 continue;
410 }
444 411
445 if (wearableCache[idx].TextureAsset != null) 412 if (cache != null)
446 { 413 {
447 if ( wearableCache[idx].TextureID != face.TextureID || 414 AssetBase asb = null;
448 wearableCache[idx].CacheId != cacheItems[i].CacheId) 415 cache.Get(face.TextureID.ToString(), out asb);
449 validDirtyBakes++; 416 wearableCache[idx].TextureAsset = asb;
417 }
450 418
451 wearableCache[idx].TextureID = face.TextureID; 419 if (wearableCache[idx].TextureAsset != null)
452 wearableCache[idx].CacheId = cacheItems[i].CacheId; 420 {
453 hits++; 421 if ( wearableCache[idx].TextureID != face.TextureID ||
454 } 422 wearableCache[idx].CacheId != cacheItems[i].CacheId)
455 else 423 validDirtyBakes++;
456 { 424
457 wearableCache[idx].CacheId = UUID.Zero; 425 wearableCache[idx].TextureID = face.TextureID;
458 wearableCache[idx].TextureID = UUID.Zero; 426 wearableCache[idx].CacheId = cacheItems[i].CacheId;
459 wearableCache[idx].TextureAsset = null; 427 hits++;
460 missing.Add(face.TextureID); 428 }
461 continue; 429 else
462 } 430 {
431 wearableCache[idx].CacheId = UUID.Zero;
432 wearableCache[idx].TextureID = UUID.Zero;
433 missing.Add(face.TextureID);
434 continue;
463 } 435 }
464 } 436 }
465 437
466 // handle optional skirt case 438 // this may be a current fs bug
467 if(!haveNewSkirt && haveSkirt) 439 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
468 { 440 {
469 wearableCache[19].CacheId = UUID.Zero; 441 uint idx = AvatarAppearance.BAKE_INDICES[i];
470 wearableCache[19].TextureID = UUID.Zero; 442 if(updatedFaces.Contains(idx))
471 wearableCache[19].TextureAsset = null; 443 continue;
472 validDirtyBakes++; 444
445 sp.Appearance.Texture.FaceTextures[idx] = null;
446
447 wearableCache[idx].CacheId = UUID.Zero;
448 wearableCache[idx].TextureID = UUID.Zero;
449 wearableCache[idx].TextureAsset = null;
473 } 450 }
474 451
475 sp.Appearance.WearableCacheItems = wearableCache; 452 sp.Appearance.WearableCacheItems = wearableCache;
@@ -480,15 +457,18 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
480 sp.ControllingClient.SendRebakeAvatarTextures(id); 457 sp.ControllingClient.SendRebakeAvatarTextures(id);
481 } 458 }
482 459
460 bool changed = false;
483 if (validDirtyBakes > 0 && hits == cacheItems.Length) 461 if (validDirtyBakes > 0 && hits == cacheItems.Length)
484 { 462 {
485 // if we got a full set of baked textures save all in BakedTextureModule 463 // if we got a full set of baked textures save all in BakedTextureModule
464 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
486 if (m_BakedTextureModule != null) 465 if (m_BakedTextureModule != null)
487 { 466 {
488 m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}", 467 m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}",
489 hits.ToString(), validDirtyBakes.ToString(), missing.Count); 468 hits.ToString(), validDirtyBakes.ToString(), missing.Count);
490 469
491 m_BakedTextureModule.Store(sp.UUID, wearableCache); 470 m_BakedTextureModule.Store(sp.UUID, wearableCache);
471 changed = true;
492 } 472 }
493 } 473 }
494 else 474 else
@@ -505,26 +485,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
505// sp.Appearance.WearableCacheItems[j].TextureID); 485// sp.Appearance.WearableCacheItems[j].TextureID);
506 } 486 }
507 487
508 return (hits == cacheItems.Length); 488 return changed;
509 } 489 }
510 490
511 // called when we get a new root avatar 491 // called when we get a new root avatar
512 public bool ValidateBakedTextureCache(IScenePresence sp) 492 public bool ValidateBakedTextureCache(IScenePresence sp)
513 { 493 {
514 int hits = 0;
515
516 if (((ScenePresence)sp).IsNPC) 494 if (((ScenePresence)sp).IsNPC)
517 return true; 495 return true;
518 496
519 lock (m_setAppearanceLock) 497 int hits = 0;
520 {
521 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
522 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
523 WearableCacheItem[] bakedModuleCache = null;
524 498
525 if (cache == null) 499 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
526 return false; 500 if (cache == null)
501 return false;
527 502
503 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
504
505 lock (m_setAppearanceLock)
506 {
528 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems; 507 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
529 508
530 // big debug 509 // big debug
@@ -566,70 +545,47 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
566 } 545 }
567 else 546 else
568 { 547 {
569 // we may have received a full cache
570 // check same coerence and store
571 wearableCacheValid = true; 548 wearableCacheValid = true;
549 Primitive.TextureEntryFace face;
572 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 550 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
573 { 551 {
574 int idx = AvatarAppearance.BAKE_INDICES[i]; 552 int idx = AvatarAppearance.BAKE_INDICES[i];
575 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; 553 face = sp.Appearance.Texture.FaceTextures[idx];
576 if (face != null) 554
555 if(face == null || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
577 { 556 {
578 if (face.TextureID == wearableCache[idx].TextureID && 557 wearableCache[idx].CacheId = UUID.Zero;
579 face.TextureID != UUID.Zero) 558 wearableCache[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
559 hits++;
560 continue;
561 }
562
563 if (face.TextureID == wearableCache[idx].TextureID &&
564 face.TextureID != UUID.Zero)
565 {
566 if (cache.Check((wearableCache[idx].TextureID).ToString()))
580 { 567 {
581 if (wearableCache[idx].TextureAsset != null) 568 hits++;
582 { 569 continue;
583 hits++;
584 wearableCache[idx].TextureAsset.Temporary = true;
585 wearableCache[idx].TextureAsset.Local = true;
586 cache.Cache(wearableCache[idx].TextureAsset);
587 wearableCache[idx].TextureAsset = null;
588 continue;
589 }
590
591 if (cache.Check((wearableCache[idx].TextureID).ToString()))
592 {
593 hits++;
594 continue;
595 }
596 } 570 }
597 wearableCacheValid = false;
598 } 571 }
572 wearableCache[idx].CacheId = UUID.Zero;
573 wearableCache[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
574 wearableCacheValid = false;
599 } 575 }
600
601 wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
602 if (wearableCacheValid)
603 {
604// m_log.Debug("[ValidateBakedCache] have valid local cache");
605 }
606 else
607 wearableCache[19].TextureAsset = null; // clear optional skirt
608 } 576 }
609 577
610 bool checkExternal = false; 578 bool checkExternal = false;
611
612 if (!wearableCacheValid) 579 if (!wearableCacheValid)
613 { 580 checkExternal = bakedModule != null;
614 hits = 0;
615 // only use external bake module on login condition check
616// ScenePresence ssp = null;
617// if (sp is ScenePresence)
618 {
619// ssp = (ScenePresence)sp;
620// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
621// bakedModule != null;
622
623 // or do it anytime we dont have the cache
624 checkExternal = bakedModule != null;
625 }
626 }
627 581
628 if (checkExternal) 582 if (checkExternal)
629 { 583 {
584 WearableCacheItem[] bakedModuleCache = null;
630 bool gotbacked = false; 585 bool gotbacked = false;
586 hits = 0;
631 587
632// m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule"); 588 // m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
633 try 589 try
634 { 590 {
635 bakedModuleCache = bakedModule.Get(sp.UUID); 591 bakedModuleCache = bakedModule.Get(sp.UUID);
@@ -647,8 +603,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
647 for (int i = 0; i < bakedModuleCache.Length; i++) 603 for (int i = 0; i < bakedModuleCache.Length; i++)
648 { 604 {
649 int j = (int)bakedModuleCache[i].TextureIndex; 605 int j = (int)bakedModuleCache[i].TextureIndex;
650 606 if (j < AvatarAppearance.TEXTURE_COUNT && bakedModuleCache[i].TextureAsset != null)
651 if (bakedModuleCache[i].TextureAsset != null)
652 { 607 {
653 wearableCache[j].TextureID = bakedModuleCache[i].TextureID; 608 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
654 wearableCache[j].CacheId = bakedModuleCache[i].CacheId; 609 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
@@ -658,33 +613,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
658 cache.Cache(bakedModuleCache[i].TextureAsset); 613 cache.Cache(bakedModuleCache[i].TextureAsset);
659 } 614 }
660 } 615 }
661 gotbacked = true;
662 }
663 616
664 if (gotbacked)
665 {
666 // force the ones we got 617 // force the ones we got
667 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 618 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
668 { 619 {
669 int idx = AvatarAppearance.BAKE_INDICES[i]; 620 int idx = AvatarAppearance.BAKE_INDICES[i];
670 if(wearableCache[idx].TextureAsset == null) 621 if (wearableCache[idx].TextureAsset == null)
671 { 622 {
672 if(idx == 19) 623 if(idx == 19)
673 { 624 {
674 sp.Appearance.Texture.FaceTextures[idx] = null; 625 sp.Appearance.Texture.FaceTextures[idx] = null;
675 hits++; 626 hits++;
676 } 627 }
628 else if(sp.Appearance.Texture.FaceTextures[idx] == null ||
629 sp.Appearance.Texture.FaceTextures[idx].TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
630 hits++;
631 wearableCache[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
632 wearableCache[idx].CacheId = UUID.Zero;
677 continue; 633 continue;
678 } 634 }
679 635
680 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; 636 Primitive.TextureEntryFace face = sp.Appearance.Texture.GetFace((uint)idx);
681
682 if (face == null)
683 {
684 face = sp.Appearance.Texture.CreateFace((uint)idx);
685 sp.Appearance.Texture.FaceTextures[idx] = face;
686 }
687
688 face.TextureID = wearableCache[idx].TextureID; 637 face.TextureID = wearableCache[idx].TextureID;
689 hits++; 638 hits++;
690 wearableCache[idx].TextureAsset = null; 639 wearableCache[idx].TextureAsset = null;
@@ -708,7 +657,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
708 sp.Appearance.WearableCacheItems[j].TextureID); 657 sp.Appearance.WearableCacheItems[j].TextureID);
709 } 658 }
710*/ 659*/
711 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional 660 return (hits >= AvatarAppearance.BAKE_INDICES.Length); // skirt is optional
712 } 661 }
713 662
714 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 663 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
@@ -776,13 +725,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
776 foreach (int i in Enum.GetValues(typeof(BakeType))) 725 foreach (int i in Enum.GetValues(typeof(BakeType)))
777 { 726 {
778 BakeType bakeType = (BakeType)i; 727 BakeType bakeType = (BakeType)i;
728 if (bakeType == BakeType.NumberOfEntries)
729 break;
779 730
780 if (bakeType == BakeType.Unknown) 731 if (bakeType == BakeType.Unknown)
781 continue; 732 continue;
782 733
783// m_log.DebugFormat( 734 // m_log.DebugFormat(
784// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}", 735 // "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}",
785// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); 736 // acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
786 737
787 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); 738 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
788 Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture 739 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
794 745
795 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea) 746 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
796 { 747 {
797 long now = DateTime.Now.Ticks; 748 if(Monitor.TryEnter(m_updatesLock))
798
799 lock (m_sendqueue)
800 { 749 {
801 Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue); 750 UUID id;
802 foreach (KeyValuePair<UUID, long> kvp in sends) 751 long now = DateTime.Now.Ticks;
752
753 foreach (KeyValuePair<UUID, long> kvp in m_sendqueue)
803 { 754 {
804 // We have to load the key and value into local parameters to avoid a race condition if we loop
805 // around and load kvp with a different value before FireAndForget has launched its thread.
806 UUID avatarID = kvp.Key;
807 long sendTime = kvp.Value; 755 long sendTime = kvp.Value;
756 if (sendTime > now)
757 continue;
808 758
809// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now); 759 id = kvp.Key;
810 760 m_sendqueue.TryRemove(id, out sendTime);
811 if (sendTime < now) 761 SendAppearance(id);
812 {
813 Util.FireAndForget(o => SendAppearance(avatarID), null, "AvatarFactoryModule.SendAppearance");
814 m_sendqueue.Remove(avatarID);
815 }
816 } 762 }
817 }
818 763
819 lock (m_savequeue) 764 if(m_updatesbusy == 0)
820 {
821 Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue);
822 foreach (KeyValuePair<UUID, long> kvp in saves)
823 { 765 {
824 // We have to load the key and value into local parameters to avoid a race condition if we loop 766 m_updatesbusy = -1;
825 // around and load kvp with a different value before FireAndForget has launched its thread. 767 List<UUID> saves = new List<UUID>(m_savequeue.Count);
826 UUID avatarID = kvp.Key; 768 foreach (KeyValuePair<UUID, long> kvp in m_savequeue)
827 long sendTime = kvp.Value; 769 {
770 long sendTime = kvp.Value;
771 if (sendTime > now)
772 continue;
773
774 id = kvp.Key;
775 m_savequeue.TryRemove(id, out sendTime);
776 saves.Add(id);
777 }
828 778
829 if (sendTime < now) 779 m_updatesbusy = 0;
780 if (saves.Count > 0)
830 { 781 {
831 Util.FireAndForget(o => SaveAppearance(avatarID), null, "AvatarFactoryModule.SaveAppearance"); 782 ++m_updatesbusy;
832 m_savequeue.Remove(avatarID); 783 WorkManager.RunInThreadPool(
784 delegate
785 {
786 SaveAppearance(saves);
787 saves = null;
788 --m_updatesbusy;
789 }, null, string.Format("SaveAppearance ({0})", m_scene.Name));
833 } 790 }
834 } 791 }
835 792
836 // We must lock both queues here so that QueueAppearanceSave() or *Send() don't m_updateTimer.Start() on 793 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
837 // another thread inbetween the first count calls and m_updateTimer.Stop() on this thread. 794 m_updateTimer.Stop();
838 lock (m_sendqueue) 795
839 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0) 796 Monitor.Exit(m_updatesLock);
840 m_updateTimer.Stop();
841 } 797 }
842 } 798 }
843 799
844 private void SaveAppearance(UUID agentid) 800 private void SaveAppearance(List<UUID> ids)
845 { 801 {
846 // We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
847 // in a culture where decimal points are commas and then reloaded in a culture which just treats them as
848 // number seperators.
849 Culture.SetCurrentCulture();
850
851 ScenePresence sp = m_scene.GetScenePresence(agentid);
852 if (sp == null)
853 {
854 // This is expected if the user has gone away.
855// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
856 return;
857 }
858
859// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); 802// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
860 803
861 // This could take awhile since it needs to pull inventory 804 foreach(UUID id in ids)
862 // 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 805 {
863 // assets and item asset id changes to complete. 806 ScenePresence sp = m_scene.GetScenePresence(id);
864 // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids 807 if(sp == null)
865 // multiple save requests. 808 continue;
866 SetAppearanceAssets(sp.UUID, sp.Appearance); 809 // This could take awhile since it needs to pull inventory
867 810 // 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
868// List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 811 // assets and item asset id changes to complete.
869// foreach (AvatarAttachment att in attachments) 812 // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
870// { 813 // multiple save requests.
871// m_log.DebugFormat(
872// "[AVFACTORY]: For {0} saving attachment {1} at point {2}",
873// sp.Name, att.ItemID, att.AttachPoint);
874// }
875 814
876 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 815 SetAppearanceAssets(id, sp.Appearance);
877 816
878 // Trigger this here because it's the final step in the set/queue/save process for appearance setting. 817 m_scene.AvatarService.SetAppearance(id, sp.Appearance);
879 // Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes). 818 //m_scene.EventManager.TriggerAvatarAppearanceChanged(sp);
880 m_scene.EventManager.TriggerAvatarAppearanceChanged(sp); 819 }
881 } 820 }
882 821
883 /// <summary> 822 /// <summary>
@@ -1231,7 +1170,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1231 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); 1170 // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId);
1232 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 1171 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
1233 if (sp != null) 1172 if (sp != null)
1234 SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems); 1173 SetAppearance(sp, textureEntry, visualParams, avSize, cacheItems);
1235 else 1174 else
1236 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); 1175 m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId);
1237 } 1176 }
@@ -1251,9 +1190,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1251 return; 1190 return;
1252 } 1191 }
1253 1192
1254 // we need to clean out the existing textures
1255 sp.Appearance.ResetAppearance();
1256
1257 // operate on a copy of the appearance so we don't have to lock anything yet 1193 // operate on a copy of the appearance so we don't have to lock anything yet
1258 AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); 1194 AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false);
1259 1195
@@ -1280,15 +1216,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1280 // often sends AvatarIsWearing and SetAppearance packets at once, and AvatarIsWearing 1216 // often sends AvatarIsWearing and SetAppearance packets at once, and AvatarIsWearing
1281 // shouldn't overwrite the changes made in SetAppearance. 1217 // shouldn't overwrite the changes made in SetAppearance.
1282 sp.Appearance.Wearables = avatAppearance.Wearables; 1218 sp.Appearance.Wearables = avatAppearance.Wearables;
1283 sp.Appearance.Texture = avatAppearance.Texture;
1284
1285 // We don't need to send the appearance here since the "iswearing" will trigger a new set 1219 // We don't need to send the appearance here since the "iswearing" will trigger a new set
1286 // of visual param and baked texture changes. When those complete, the new appearance will be sent 1220 // of visual param and baked texture changes. When those complete, the new appearance will be sent
1287
1288 QueueAppearanceSave(client.AgentId); 1221 QueueAppearanceSave(client.AgentId);
1289 } 1222 }
1290 } 1223 }
1291 1224
1225/*
1292 /// <summary> 1226 /// <summary>
1293 /// Respond to the cached textures request from the client 1227 /// Respond to the cached textures request from the client
1294 /// </summary> 1228 /// </summary>
@@ -1308,23 +1242,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1308 1242
1309 if (m_reusetextures) 1243 if (m_reusetextures)
1310 { 1244 {
1311 // this is the most insanely dumb way to do this... however it seems to
1312 // actually work. if the appearance has been reset because wearables have
1313 // changed then the texture entries are zero'd out until the bakes are
1314 // uploaded. on login, if the textures exist in the cache (eg if you logged
1315 // into the simulator recently, then the appearance will pull those and send
1316 // them back in the packet and you won't have to rebake. if the textures aren't
1317 // in the cache then the intial makeroot() call in scenepresence will zero
1318 // them out.
1319 //
1320 // a better solution (though how much better is an open question) is to
1321 // store the hashes in the appearance and compare them. Thats's coming.
1322
1323 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index]; 1245 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
1324 if (face != null) 1246 if (face != null)
1325 texture = face.TextureID; 1247 texture = face.TextureID;
1326
1327 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1328 } 1248 }
1329 1249
1330 CachedTextureResponseArg response = new CachedTextureResponseArg(); 1250 CachedTextureResponseArg response = new CachedTextureResponseArg();
@@ -1334,21 +1254,16 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1334 1254
1335 cachedTextureResponse.Add(response); 1255 cachedTextureResponse.Add(response);
1336 } 1256 }
1337
1338 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1339 // The serial number appears to be used to match requests and responses
1340 // in the texture transaction. We just send back the serial number
1341 // that was provided in the request. The viewer bumps this for us.
1342 client.SendCachedTextureResponse(sp, serial, cachedTextureResponse); 1257 client.SendCachedTextureResponse(sp, serial, cachedTextureResponse);
1343 } 1258 }
1344 1259*/
1345 1260
1346 #endregion 1261 #endregion
1347 1262
1348 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction) 1263 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
1349 { 1264 {
1350 outputAction("For {0} in {1}", sp.Name, m_scene.RegionInfo.RegionName); 1265 outputAction("For {0} in {1}", null, sp.Name, m_scene.RegionInfo.RegionName);
1351 outputAction(BAKED_TEXTURES_REPORT_FORMAT, "Bake Type", "UUID"); 1266 outputAction(BAKED_TEXTURES_REPORT_FORMAT, null, "Bake Type", "UUID");
1352 1267
1353 Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp.UUID); 1268 Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = GetBakedTextureFaces(sp.UUID);
1354 1269
@@ -1362,19 +1277,38 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1362 } 1277 }
1363 else 1278 else
1364 { 1279 {
1365 rawTextureID = bakedTextures[bt].TextureID.ToString(); 1280 if(bakedTextures[bt].TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
1366 1281 rawTextureID = "not set";
1367 if (m_scene.AssetService.Get(rawTextureID) == null)
1368 rawTextureID += " (not found)";
1369 else 1282 else
1370 rawTextureID += " (uploaded)"; 1283 {
1284 rawTextureID = bakedTextures[bt].TextureID.ToString();
1285
1286 if (m_scene.AssetService.Get(rawTextureID) == null)
1287 rawTextureID += " (not found)";
1288 else
1289 rawTextureID += " (uploaded)";
1290 }
1371 } 1291 }
1372 1292
1373 outputAction(BAKED_TEXTURES_REPORT_FORMAT, null, bt, rawTextureID); 1293 outputAction(BAKED_TEXTURES_REPORT_FORMAT, null, bt, rawTextureID);
1374 } 1294 }
1375 1295
1376 bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp); 1296 bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp);
1377 outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete"); 1297 outputAction("{0} baked appearance texture is {1}", null, sp.Name, bakedTextureValid ? "OK" : "incomplete");
1298 }
1299
1300 public void SetPreferencesHoverZ(UUID agentId, float val)
1301 {
1302 ScenePresence sp = m_scene.GetScenePresence(agentId);
1303 if (sp == null || sp.IsDeleted || sp.IsNPC || sp.IsInTransit)
1304 return;
1305 float last = sp.Appearance.AvatarPreferencesHoverZ;
1306 if(val != last)
1307 {
1308 sp.Appearance.AvatarPreferencesHoverZ = val;
1309 //sp.SendAppearanceToAgentNF(sp);
1310 QueueAppearanceSend(agentId);
1311 }
1378 } 1312 }
1379 } 1313 }
1380} 1314}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 187df31..c55f535 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
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]"; 55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
56 private static readonly string OutfitTPError = "destination region does not support the Outfit you are wearing. Please retry with a simpler one";
56 57
57 public const bool WaitForAgentArrivedAtDestinationDefault = true; 58 public const bool WaitForAgentArrivedAtDestinationDefault = true;
58 59
@@ -720,6 +721,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
720 return; 721 return;
721 } 722 }
722 723
724 if (!sp.Appearance.CanTeleport(ctx.OutboundVersion))
725 {
726 sp.ControllingClient.SendTeleportFailed(OutfitTPError);
727
728 m_log.DebugFormat(
729 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because: {3}",
730 sp.Name, sp.Scene.Name, finalDestination.RegionName, "incompatible wearable");
731
732 return;
733 }
734
723 // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target 735 // Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target
724 // simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these 736 // simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these
725 // as server attempts. 737 // as server attempts.
@@ -1489,6 +1501,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1489 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0); 1501 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
1490 return false; 1502 return false;
1491 } 1503 }
1504 if (!agent.Appearance.CanTeleport(ctx.OutboundVersion))
1505 {
1506 reason = OutfitTPError;
1507 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
1508 return false;
1509 }
1510
1492 return true; 1511 return true;
1493 } 1512 }
1494 1513
@@ -1545,7 +1564,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1545 failureReason = "Access Denied"; 1564 failureReason = "Access Denied";
1546 return null; 1565 return null;
1547 } 1566 }
1548
1549 return neighbourRegion; 1567 return neighbourRegion;
1550 } 1568 }
1551 1569
@@ -1599,9 +1617,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1599 agent.ControllingClient.SendAlertMessage(failureReason); 1617 agent.ControllingClient.SendAlertMessage(failureReason);
1600 return agent; 1618 return agent;
1601 } 1619 }
1620 if (!agent.Appearance.CanTeleport(ctx.OutboundVersion))
1621 {
1622 if (agent.ControllingClient != null)
1623 agent.ControllingClient.SendAlertMessage(OutfitTPError);
1624 return agent;
1625 }
1602 1626
1603// agent.IsInTransit = true; 1627 // agent.IsInTransit = true;
1604
1605 CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx); 1628 CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
1606 agent.IsInTransit = false; 1629 agent.IsInTransit = false;
1607 return agent; 1630 return agent;
@@ -2601,7 +2624,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2601 string reason = String.Empty; 2624 string reason = String.Empty;
2602 2625
2603 EntityTransferContext ctx = new EntityTransferContext(); 2626 EntityTransferContext ctx = new EntityTransferContext();
2604 bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, agentCircData, (uint)TeleportFlags.Default, ctx, out reason); 2627 bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, agentCircData, (uint)TeleportFlags.Default, null, out reason);
2605 2628
2606 if (regionAccepted) 2629 if (regionAccepted)
2607 { 2630 {
diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
index 800affe..8faf4a8 100755
--- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.Framework.Interfaces
37 { 37 {
38 void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems); 38 void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems);
39 void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems); 39 void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems);
40 40 void SetPreferencesHoverZ(UUID agentId, float val);
41 /// <summary> 41 /// <summary>
42 /// Send the appearance of an avatar to others in the scene. 42 /// Send the appearance of an avatar to others in the scene.
43 /// </summary> 43 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index d53c562..9db7633 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -4358,16 +4358,7 @@ namespace OpenSim.Region.Framework.Scenes
4358 4358
4359 public void SendAppearanceToAgentNF(ScenePresence avatar) 4359 public void SendAppearanceToAgentNF(ScenePresence avatar)
4360 { 4360 {
4361 if(avatar.UUID == UUID) 4361 avatar.ControllingClient.SendAppearance(UUID, Appearance.VisualParams, Appearance.Texture.GetBakesBytes(), Appearance.AvatarPreferencesHoverZ);
4362 {
4363 avatar.ControllingClient.SendAppearance(
4364 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
4365 }
4366 else
4367 {
4368 avatar.ControllingClient.SendAppearance(
4369 UUID, Appearance.VisualParams, Appearance.Texture.GetBakesBytes());
4370 }
4371 } 4362 }
4372 4363
4373 public void SendAnimPackToAgent(ScenePresence p) 4364 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 002bfad..009c72e 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
961 961
962 } 962 }
963 963
964 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) 964 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hoverheight)
965 { 965 {
966 966
967 } 967 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
index ded0857..1db9ba7 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
413 sb.AppendFormat("Wearables checks for {0}\n\n", sp.Name); 413 sb.AppendFormat("Wearables checks for {0}\n\n", sp.Name);
414 414
415 AvatarWearable[] wearables = sp.Appearance.Wearables; 415 AvatarWearable[] wearables = sp.Appearance.Wearables;
416 if(wearables.Count() == 0) 416 if(wearables.Length == 0)
417 { 417 {
418 MainConsole.Instance.Output("avatar has no wearables"); 418 MainConsole.Instance.Output("avatar has no wearables");
419 return; 419 return;
420 } 420 }
421 421
422 for (int i = 0; i < wearables.Count(); i++) 422 for (int i = 0; i < wearables.Length; i++)
423 { 423 {
424 AvatarWearable aw = wearables[i]; 424 AvatarWearable aw = wearables[i];
425 425
@@ -477,8 +477,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
477 cdt.AddColumn("Type", 10); 477 cdt.AddColumn("Type", 10);
478 cdt.AddColumn("Item UUID", ConsoleDisplayUtil.UuidSize); 478 cdt.AddColumn("Item UUID", ConsoleDisplayUtil.UuidSize);
479 cdt.AddColumn("Asset UUID", ConsoleDisplayUtil.UuidSize); 479 cdt.AddColumn("Asset UUID", ConsoleDisplayUtil.UuidSize);
480 AvatarWearable[] wearables = sp.Appearance.Wearables;
480 481
481 for (int i = (int)WearableType.Shape; i < (int)WearableType.Physics; i++) 482 for (int i = 0; i < wearables.Length; i++)
482 { 483 {
483 AvatarWearable aw = sp.Appearance.Wearables[i]; 484 AvatarWearable aw = sp.Appearance.Wearables[i];
484 485
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 798576c..1eb77a7 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
664 { 664 {
665 } 665 }
666 666
667 public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) 667 public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hover)
668 { 668 {
669 } 669 }
670 670
diff --git a/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs b/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs
index b1b3c6f..2f8f151 100644
--- a/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/AgentPreferences/AgentPreferencesServerPostHandler.cs
@@ -129,7 +129,7 @@ namespace OpenSim.Server.Handlers.AgentPreferences
129 129
130 AgentPrefs data = new AgentPrefs(userID); 130 AgentPrefs data = new AgentPrefs(userID);
131 data.AccessPrefs = request["AccessPrefs"].ToString(); 131 data.AccessPrefs = request["AccessPrefs"].ToString();
132 data.HoverHeight = double.Parse(request["HoverHeight"].ToString()); 132 data.HoverHeight = float.Parse(request["HoverHeight"].ToString());
133 data.Language = request["Language"].ToString(); 133 data.Language = request["Language"].ToString();
134 data.LanguageIsPublic = bool.Parse(request["LanguageIsPublic"].ToString()); 134 data.LanguageIsPublic = bool.Parse(request["LanguageIsPublic"].ToString());
135 data.PermEveryone = int.Parse(request["PermEveryone"].ToString()); 135 data.PermEveryone = int.Parse(request["PermEveryone"].ToString());
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index f5e7771..18c949e 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -116,6 +116,8 @@ namespace OpenSim.Services.Connectors.Simulation
116 try 116 try
117 { 117 {
118 OSDMap args = aCircuit.PackAgentCircuitData(ctx); 118 OSDMap args = aCircuit.PackAgentCircuitData(ctx);
119 if(ctx == null)
120 ctx = new EntityTransferContext();
119 args["context"] = ctx.Pack(); 121 args["context"] = ctx.Pack();
120 PackData(args, source, aCircuit, destination, flags); 122 PackData(args, source, aCircuit, destination, flags);
121 123
diff --git a/OpenSim/Services/Interfaces/IAgentPreferencesService.cs b/OpenSim/Services/Interfaces/IAgentPreferencesService.cs
index af92326..6d2ce8f 100644
--- a/OpenSim/Services/Interfaces/IAgentPreferencesService.cs
+++ b/OpenSim/Services/Interfaces/IAgentPreferencesService.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Services.Interfaces
45 if (kvp.ContainsKey("AccessPrefs")) 45 if (kvp.ContainsKey("AccessPrefs"))
46 AccessPrefs = kvp["AccessPrefs"]; 46 AccessPrefs = kvp["AccessPrefs"];
47 if (kvp.ContainsKey("HoverHeight")) 47 if (kvp.ContainsKey("HoverHeight"))
48 HoverHeight = double.Parse(kvp["HoverHeight"]); 48 HoverHeight = float.Parse(kvp["HoverHeight"]);
49 if (kvp.ContainsKey("Language")) 49 if (kvp.ContainsKey("Language"))
50 Language = kvp["Language"]; 50 Language = kvp["Language"];
51 if (kvp.ContainsKey("LanguageIsPublic")) 51 if (kvp.ContainsKey("LanguageIsPublic"))
@@ -65,7 +65,7 @@ namespace OpenSim.Services.Interfaces
65 if (kvp.ContainsKey("AccessPrefs")) 65 if (kvp.ContainsKey("AccessPrefs"))
66 AccessPrefs = kvp["AccessPrefs"].ToString(); 66 AccessPrefs = kvp["AccessPrefs"].ToString();
67 if (kvp.ContainsKey("HoverHeight")) 67 if (kvp.ContainsKey("HoverHeight"))
68 HoverHeight = double.Parse(kvp["HoverHeight"].ToString()); 68 HoverHeight = float.Parse(kvp["HoverHeight"].ToString());
69 if (kvp.ContainsKey("Language")) 69 if (kvp.ContainsKey("Language"))
70 Language = kvp["Language"].ToString(); 70 Language = kvp["Language"].ToString();
71 if (kvp.ContainsKey("LanguageIsPublic")) 71 if (kvp.ContainsKey("LanguageIsPublic"))
@@ -95,7 +95,7 @@ namespace OpenSim.Services.Interfaces
95 public UUID PrincipalID = UUID.Zero; 95 public UUID PrincipalID = UUID.Zero;
96 public string AccessPrefs = "M"; 96 public string AccessPrefs = "M";
97 //public int GodLevel; // *TODO: Implement GodLevel (Unused by the viewer, afaict - 6/11/2015) 97 //public int GodLevel; // *TODO: Implement GodLevel (Unused by the viewer, afaict - 6/11/2015)
98 public double HoverHeight = 0.0; 98 public float HoverHeight = 0.0f;
99 public string Language = "en-us"; 99 public string Language = "en-us";
100 public bool LanguageIsPublic = true; 100 public bool LanguageIsPublic = true;
101 // DefaultObjectPermMasks 101 // DefaultObjectPermMasks
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 6cea71f..929fa4a 100755
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -570,7 +570,7 @@ namespace OpenSim.Tests.Common
570 { 570 {
571 } 571 }
572 572
573 public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) 573 public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hover)
574 { 574 {
575 } 575 }
576 576