aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie2010-10-29 21:06:46 +0100
committerMelanie2010-10-29 21:06:46 +0100
commit934e53673856876762df27c7880df30df633ccd3 (patch)
treeb50129669f9d7f725cf63db1df60c600b8da9f0c
parentAdd my work on top of cmickeyb's (diff)
parentClean up some cruft from the last commit. Re-add the initial update (diff)
downloadopensim-SC_OLD-934e53673856876762df27c7880df30df633ccd3.zip
opensim-SC_OLD-934e53673856876762df27c7880df30df633ccd3.tar.gz
opensim-SC_OLD-934e53673856876762df27c7880df30df633ccd3.tar.bz2
opensim-SC_OLD-934e53673856876762df27c7880df30df633ccd3.tar.xz
Merge commit 'cmickeyb/dev-appearance'
Diffstat (limited to '')
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs8
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs25
-rw-r--r--OpenSim/Framework/AgentCircuitData.cs66
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs186
-rw-r--r--OpenSim/Framework/Capabilities/Caps.cs14
-rw-r--r--OpenSim/Framework/ChildAgentDataUpdate.cs98
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs32
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs277
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs73
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs15
-rw-r--r--OpenSim/Services/Interfaces/IAvatarService.cs16
-rw-r--r--bin/OpenSimDefaults.ini14
14 files changed, 567 insertions, 303 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 0589748..1829c8d 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -1614,12 +1614,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1614 } 1614 }
1615 1615
1616 // Attachments 1616 // Attachments
1617 Dictionary<int, AvatarAttachment> attachments = avatarAppearance.Attachments; 1617 List<AvatarAttachment> attachments = avatarAppearance.GetAttachments();
1618 1618
1619 foreach (KeyValuePair<int, AvatarAttachment> attachment in attachments) 1619 foreach (AvatarAttachment attachment in attachments)
1620 { 1620 {
1621 int attachpoint = attachment.Value.AttachPoint; 1621 int attachpoint = attachment.AttachPoint;
1622 UUID itemID = attachment.Value.ItemID; 1622 UUID itemID = attachment.ItemID;
1623 1623
1624 if (itemID != UUID.Zero) 1624 if (itemID != UUID.Zero)
1625 { 1625 {
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs
index 8271d76..3f6d4d6 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Xml; 31using System.Xml;
31using OpenMetaverse; 32using OpenMetaverse;
32using OpenSim.Framework; 33using OpenSim.Framework;
@@ -765,25 +766,19 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
765 FormatPart(rdata, "UnderShirt", rdata.userAppearance.UnderShirtItem, rdata.userAppearance.UnderShirtAsset); 766 FormatPart(rdata, "UnderShirt", rdata.userAppearance.UnderShirtItem, rdata.userAppearance.UnderShirtAsset);
766 FormatPart(rdata, "UnderPants", rdata.userAppearance.UnderPantsItem, rdata.userAppearance.UnderPantsAsset); 767 FormatPart(rdata, "UnderPants", rdata.userAppearance.UnderPantsItem, rdata.userAppearance.UnderPantsAsset);
767 768
768 Hashtable attachments = rdata.userAppearance.GetAttachments(); 769 Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting attachments", MsgId);
769 770
770 if (attachments != null) 771 rdata.writer.WriteStartElement("Attachments");
772 List<AvatarAttachment> attachments = rdata.userAppearance.GetAttachments();
773 foreach (AvatarAttachment attach in attachments)
771 { 774 {
772 775 rdata.writer.WriteStartElement("Attachment");
773 Rest.Log.DebugFormat("{0} FormatUserAppearance: Formatting attachments", MsgId); 776 rdata.writer.WriteAttributeString("AtPoint", attach.AttachPoint.ToString());
774 777 rdata.writer.WriteAttributeString("Item", attach.ItemID.ToString());
775 rdata.writer.WriteStartElement("Attachments"); 778 rdata.writer.WriteAttributeString("Asset", attach.AssetID.ToString());
776 for (int i = 0; i < attachments.Count; i++)
777 {
778 Hashtable attachment = attachments[i] as Hashtable;
779 rdata.writer.WriteStartElement("Attachment");
780 rdata.writer.WriteAttributeString("AtPoint", i.ToString());
781 rdata.writer.WriteAttributeString("Item", (string) attachment["item"]);
782 rdata.writer.WriteAttributeString("Asset", (string) attachment["asset"]);
783 rdata.writer.WriteEndElement();
784 }
785 rdata.writer.WriteEndElement(); 779 rdata.writer.WriteEndElement();
786 } 780 }
781 rdata.writer.WriteEndElement();
787 782
788 Primitive.TextureEntry texture = rdata.userAppearance.Texture; 783 Primitive.TextureEntry texture = rdata.userAppearance.Texture;
789 784
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index be98380..640a646 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -206,16 +206,18 @@ namespace OpenSim.Framework
206 206
207 args["service_session_id"] = OSD.FromString(ServiceSessionID); 207 args["service_session_id"] = OSD.FromString(ServiceSessionID);
208 args["start_pos"] = OSD.FromString(startpos.ToString()); 208 args["start_pos"] = OSD.FromString(startpos.ToString());
209 args["appearance_serial"] = OSD.FromInteger(Appearance.Serial);
210 args["client_ip"] = OSD.FromString(IPAddress); 209 args["client_ip"] = OSD.FromString(IPAddress);
211 args["viewer"] = OSD.FromString(Viewer); 210 args["viewer"] = OSD.FromString(Viewer);
212 args["channel"] = OSD.FromString(Channel); 211 args["channel"] = OSD.FromString(Channel);
213 args["mac"] = OSD.FromString(Mac); 212 args["mac"] = OSD.FromString(Mac);
214 args["id0"] = OSD.FromString(Id0); 213 args["id0"] = OSD.FromString(Id0);
215 214
216/* 215 // Eventually this code should be deprecated, use full appearance
216 // packing in packed_appearance
217 if (Appearance != null) 217 if (Appearance != null)
218 { 218 {
219 args["appearance_serial"] = OSD.FromInteger(Appearance.Serial);
220
219 //System.Console.WriteLine("XXX Before packing Wearables"); 221 //System.Console.WriteLine("XXX Before packing Wearables");
220 if ((Appearance.Wearables != null) && (Appearance.Wearables.Length > 0)) 222 if ((Appearance.Wearables != null) && (Appearance.Wearables.Length > 0))
221 { 223 {
@@ -230,20 +232,19 @@ namespace OpenSim.Framework
230 } 232 }
231 233
232 //System.Console.WriteLine("XXX Before packing Attachments"); 234 //System.Console.WriteLine("XXX Before packing Attachments");
233 Dictionary<int, AvatarAttachment> attachments = Appearance.Attachments; 235 List<AvatarAttachment> attachments = Appearance.GetAttachments();
234 if ((attachments != null) && (attachments.Count > 0)) 236 if ((attachments != null) && (attachments.Count > 0))
235 { 237 {
236 OSDArray attachs = new OSDArray(attachments.Count); 238 OSDArray attachs = new OSDArray(attachments.Count);
237 foreach (KeyValuePair<int, AvatarAttachment> kvp in attachments) 239 foreach (AvatarAttachment attach in attachments)
238 { 240 {
239 AvatarAttachment adata = new AvatarAttachment(kvp.Value); 241 attachs.Add(attach.Pack());
240 attachs.Add(adata.Pack());
241 //System.Console.WriteLine("XXX att.pt=" + kvp.Key + "; itemID=" + kvp.Value[0] + "; assetID=" + kvp.Value[1]); 242 //System.Console.WriteLine("XXX att.pt=" + kvp.Key + "; itemID=" + kvp.Value[0] + "; assetID=" + kvp.Value[1]);
242 } 243 }
243 args["attachments"] = attachs; 244 args["attachments"] = attachs;
244 } 245 }
245 } 246 }
246*/ 247
247 if (Appearance != null) 248 if (Appearance != null)
248 { 249 {
249 OSDMap appmap = Appearance.Pack(); 250 OSDMap appmap = Appearance.Pack();
@@ -339,27 +340,9 @@ namespace OpenSim.Framework
339 try { 340 try {
340 // Unpack various appearance elements 341 // Unpack various appearance elements
341 Appearance = new AvatarAppearance(AgentID); 342 Appearance = new AvatarAppearance(AgentID);
342 if (args["packed_appearance"] != null) 343
343 { 344 // Eventually this code should be deprecated, use full appearance
344 if (args["packed_appearance"].Type == OSDType.Map) 345 // packing in packed_appearance
345 {
346 Appearance.Unpack((OSDMap)args["packed_appearance"]);
347 m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance");
348 }
349 else
350 m_log.WarnFormat("[AGENTCIRCUITDATA] packed_appearance is not a map:\n{0}",args["packed_appearance"].ToString());
351 }
352// DEBUG ON
353 else
354 m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance");
355// DEBUG OFF
356 } catch (Exception e)
357 {
358 m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message);
359 }
360
361
362/*
363 if (args["appearance_serial"] != null) 346 if (args["appearance_serial"] != null)
364 Appearance.Serial = args["appearance_serial"].AsInteger(); 347 Appearance.Serial = args["appearance_serial"].AsInteger();
365 348
@@ -368,26 +351,39 @@ namespace OpenSim.Framework
368 OSDArray wears = (OSDArray)(args["wearables"]); 351 OSDArray wears = (OSDArray)(args["wearables"]);
369 for (int i = 0; i < wears.Count / 2; i++) 352 for (int i = 0; i < wears.Count / 2; i++)
370 { 353 {
371 Appearance.Wearables[i].ItemID = wears[i*2].AsUUID(); 354 AvatarWearable awear = new AvatarWearable(wears[i*2].AsUUID(),wears[(i*2)+1].AsUUID());
372 Appearance.Wearables[i].AssetID = wears[(i*2)+1].AsUUID(); 355 Appearance.SetWearable(i,awear);
373 } 356 }
374 } 357 }
375 358
376 if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) 359 if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array)
377 { 360 {
378 OSDArray attachs = (OSDArray)(args["attachments"]); 361 OSDArray attachs = (OSDArray)(args["attachments"]);
379 AvatarAttachment[] attachments = new AvatarAttachment[attachs.Count];
380 int i = 0;
381 foreach (OSD o in attachs) 362 foreach (OSD o in attachs)
382 { 363 {
383 if (o.Type == OSDType.Map) 364 if (o.Type == OSDType.Map)
384 { 365 {
385 attachments[i++] = new AvatarAttachment((OSDMap)o); 366 Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o));
386 } 367 }
387 } 368 }
388 Appearance.SetAttachments(attachments);
389 } 369 }
390*/ 370
371 if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map))
372 {
373 Appearance.Unpack((OSDMap)args["packed_appearance"]);
374// DEBUG ON
375 m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance");
376// DEBUG OFF
377 }
378// DEBUG ON
379 else
380 m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance");
381// DEBUG OFF
382 } catch (Exception e)
383 {
384 m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message);
385 }
386
391 ServiceURLs = new Dictionary<string, object>(); 387 ServiceURLs = new Dictionary<string, object>();
392 if (args.ContainsKey("service_urls") && args["service_urls"] != null && (args["service_urls"]).Type == OSDType.Array) 388 if (args.ContainsKey("service_urls") && args["service_urls"] != null && (args["service_urls"]).Type == OSDType.Array)
393 { 389 {
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 4738d88..a4bb765 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -143,13 +143,14 @@ namespace OpenSim.Framework
143 public readonly static int VISUALPARAM_COUNT = 218; 143 public readonly static int VISUALPARAM_COUNT = 218;
144 144
145 public readonly static int TEXTURE_COUNT = 21; 145 public readonly static int TEXTURE_COUNT = 21;
146 public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
146 147
147 protected UUID m_owner; 148 protected UUID m_owner;
148 protected int m_serial = 1; 149 protected int m_serial = 1;
149 protected byte[] m_visualparams; 150 protected byte[] m_visualparams;
150 protected Primitive.TextureEntry m_texture; 151 protected Primitive.TextureEntry m_texture;
151 protected AvatarWearable[] m_wearables; 152 protected AvatarWearable[] m_wearables;
152 protected Dictionary<int, AvatarAttachment> m_attachments; 153 protected Dictionary<int, List<AvatarAttachment>> m_attachments;
153 protected float m_avatarHeight = 0; 154 protected float m_avatarHeight = 0;
154 protected float m_hipOffset = 0; 155 protected float m_hipOffset = 0;
155 156
@@ -183,11 +184,6 @@ namespace OpenSim.Framework
183 set { m_wearables = value; } 184 set { m_wearables = value; }
184 } 185 }
185 186
186 public virtual Dictionary<int, AvatarAttachment> Attachments
187 {
188 get { return m_attachments; }
189 }
190
191 public virtual UUID BodyItem { 187 public virtual UUID BodyItem {
192 get { return m_wearables[AvatarWearable.BODY].ItemID; } 188 get { return m_wearables[AvatarWearable.BODY].ItemID; }
193 set { m_wearables[AvatarWearable.BODY].ItemID = value; } 189 set { m_wearables[AvatarWearable.BODY].ItemID = value; }
@@ -336,7 +332,7 @@ namespace OpenSim.Framework
336// DEBUG ON 332// DEBUG ON
337 m_log.WarnFormat("[AVATAR APPEARANCE] create empty appearance for {0}",owner); 333 m_log.WarnFormat("[AVATAR APPEARANCE] create empty appearance for {0}",owner);
338// DEBUG OFF 334// DEBUG OFF
339 m_serial = 0; 335 m_serial = 1;
340 m_owner = owner; 336 m_owner = owner;
341 337
342 SetDefaultWearables(); 338 SetDefaultWearables();
@@ -344,7 +340,7 @@ namespace OpenSim.Framework
344 SetDefaultParams(); 340 SetDefaultParams();
345 SetHeight(); 341 SetHeight();
346 342
347 m_attachments = new Dictionary<int, AvatarAttachment>(); 343 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
348 } 344 }
349 345
350 public AvatarAppearance(UUID avatarID, OSDMap map) 346 public AvatarAppearance(UUID avatarID, OSDMap map)
@@ -382,7 +378,7 @@ namespace OpenSim.Framework
382 378
383 SetHeight(); 379 SetHeight();
384 380
385 m_attachments = new Dictionary<int, AvatarAttachment>(); 381 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
386 } 382 }
387 383
388 public AvatarAppearance(AvatarAppearance appearance) 384 public AvatarAppearance(AvatarAppearance appearance)
@@ -392,7 +388,7 @@ namespace OpenSim.Framework
392// DEBUG OFF 388// DEBUG OFF
393 if (appearance == null) 389 if (appearance == null)
394 { 390 {
395 m_serial = 0; 391 m_serial = 1;
396 m_owner = UUID.Zero; 392 m_owner = UUID.Zero;
397 393
398 SetDefaultWearables(); 394 SetDefaultWearables();
@@ -400,7 +396,7 @@ namespace OpenSim.Framework
400 SetDefaultParams(); 396 SetDefaultParams();
401 SetHeight(); 397 SetHeight();
402 398
403 m_attachments = new Dictionary<int, AvatarAttachment>(); 399 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
404 400
405 return; 401 return;
406 } 402 }
@@ -427,9 +423,10 @@ namespace OpenSim.Framework
427 if (appearance.VisualParams != null) 423 if (appearance.VisualParams != null)
428 m_visualparams = (byte[])appearance.VisualParams.Clone(); 424 m_visualparams = (byte[])appearance.VisualParams.Clone();
429 425
430 m_attachments = new Dictionary<int, AvatarAttachment>(); 426 // Copy the attachment, force append mode since that ensures consistency
431 foreach (KeyValuePair<int, AvatarAttachment> kvp in appearance.Attachments) 427 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
432 m_attachments[kvp.Key] = new AvatarAttachment(kvp.Value); 428 foreach (AvatarAttachment attachment in appearance.GetAttachments())
429 AppendAttachment(new AvatarAttachment(attachment));
433 } 430 }
434 431
435 protected virtual void SetDefaultWearables() 432 protected virtual void SetDefaultWearables()
@@ -449,14 +446,8 @@ namespace OpenSim.Framework
449 protected virtual void SetDefaultTexture() 446 protected virtual void SetDefaultTexture()
450 { 447 {
451 m_texture = new Primitive.TextureEntry(new UUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97")); 448 m_texture = new Primitive.TextureEntry(new UUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97"));
452 // The initialization of these seems to force a rebake regardless of whether it is needed 449 for (uint i = 0; i < TEXTURE_COUNT; i++)
453 // m_textures.CreateFace(0).TextureID = new UUID("00000000-0000-1111-9999-000000000012"); 450 m_texture.CreateFace(i).TextureID = new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE);
454 // m_textures.CreateFace(1).TextureID = Util.BLANK_TEXTURE_UUID;
455 // m_textures.CreateFace(2).TextureID = Util.BLANK_TEXTURE_UUID;
456 // m_textures.CreateFace(3).TextureID = new UUID("6522E74D-1660-4E7F-B601-6F48C1659A77");
457 // m_textures.CreateFace(4).TextureID = new UUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B");
458 // m_textures.CreateFace(5).TextureID = new UUID("00000000-0000-1111-9999-000000000010");
459 // m_textures.CreateFace(6).TextureID = new UUID("00000000-0000-1111-9999-000000000011");
460 } 451 }
461 452
462 /// <summary> 453 /// <summary>
@@ -473,7 +464,7 @@ namespace OpenSim.Framework
473 // made. We determine if any of the textures actually 464 // made. We determine if any of the textures actually
474 // changed to know if the appearance should be saved later 465 // changed to know if the appearance should be saved later
475 bool changed = false; 466 bool changed = false;
476 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) 467 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
477 { 468 {
478 Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i]; 469 Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i];
479 Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i]; 470 Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i];
@@ -487,14 +478,14 @@ namespace OpenSim.Framework
487 if (oldface != null && oldface.TextureID == newface.TextureID) continue; 478 if (oldface != null && oldface.TextureID == newface.TextureID) continue;
488 } 479 }
489 480
490 m_texture.FaceTextures[i] = (newface != null) ? new Primitive.TextureEntryFace(newface) : null;
491 changed = true; 481 changed = true;
492// DEBUG ON 482// DEBUG ON
493 if (newface != null) 483 if (newface != null)
494 m_log.WarnFormat("[SCENEPRESENCE] index {0}, new texture id {1}",i,newface.TextureID); 484 m_log.WarnFormat("[AVATAR APPEARANCE] index {0}, new texture id {1}",i,newface.TextureID);
495// DEBUG OFF 485// DEBUG OFF
496 } 486 }
497 487
488 m_texture = textureEntry;
498 return changed; 489 return changed;
499 } 490 }
500 491
@@ -517,8 +508,8 @@ namespace OpenSim.Framework
517 if (visualParams[i] != m_visualparams[i]) 508 if (visualParams[i] != m_visualparams[i])
518 { 509 {
519// DEBUG ON 510// DEBUG ON
520 m_log.WarnFormat("[AVATARAPPEARANCE] vparams changed [{0}] {1} ==> {2}", 511// m_log.WarnFormat("[AVATARAPPEARANCE] vparams changed [{0}] {1} ==> {2}",
521 i,m_visualparams[i],visualParams[i]); 512// i,m_visualparams[i],visualParams[i]);
522// DEBUG OFF 513// DEBUG OFF
523 m_visualparams[i] = visualParams[i]; 514 m_visualparams[i] = visualParams[i];
524 changed = true; 515 changed = true;
@@ -569,6 +560,9 @@ namespace OpenSim.Framework
569 public override String ToString() 560 public override String ToString()
570 { 561 {
571 String s = ""; 562 String s = "";
563
564 s += String.Format("Serial: {0}\n",m_serial);
565
572 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) 566 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
573 if (m_texture.FaceTextures[i] != null) 567 if (m_texture.FaceTextures[i] != null)
574 s += String.Format("Texture: {0} --> {1}\n",i,m_texture.FaceTextures[i].TextureID); 568 s += String.Format("Texture: {0} --> {1}\n",i,m_texture.FaceTextures[i].TextureID);
@@ -585,12 +579,41 @@ namespace OpenSim.Framework
585 } 579 }
586// DEBUG OFF 580// DEBUG OFF
587 581
588 public void SetAttachments(AvatarAttachment[] data) 582 /// <summary>
583 /// Get a list of the attachments, note that there may be
584 /// duplicate attachpoints
585 /// </summary>
586 public List<AvatarAttachment> GetAttachments()
587 {
588 List<AvatarAttachment> alist = new List<AvatarAttachment>();
589 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
590 {
591 foreach (AvatarAttachment attach in kvp.Value)
592 alist.Add(new AvatarAttachment(attach));
593 }
594
595 return alist;
596 }
597
598 internal void AppendAttachment(AvatarAttachment attach)
589 { 599 {
590 foreach (AvatarAttachment attach in data) 600 if (! m_attachments.ContainsKey(attach.AttachPoint))
591 m_attachments[attach.AttachPoint] = new AvatarAttachment(attach); 601 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
602 m_attachments[attach.AttachPoint].Add(attach);
592 } 603 }
593 604
605 internal void ReplaceAttachment(AvatarAttachment attach)
606 {
607 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
608 m_attachments[attach.AttachPoint].Add(attach);
609 }
610
611 /// <summary>
612 /// Add an attachment, if the attachpoint has the
613 /// 0x80 bit set then we assume this is an append
614 /// operation otherwise we replace whatever is
615 /// currently attached at the attachpoint
616 /// </summary>
594 public void SetAttachment(int attachpoint, UUID item, UUID asset) 617 public void SetAttachment(int attachpoint, UUID item, UUID asset)
595 { 618 {
596 if (attachpoint == 0) 619 if (attachpoint == 0)
@@ -603,67 +626,47 @@ namespace OpenSim.Framework
603 return; 626 return;
604 } 627 }
605 628
606 m_attachments[attachpoint] = new AvatarAttachment(attachpoint,item,asset); 629 // check if this is an append or a replace, 0x80 marks it as an append
607 } 630 if ((attachpoint & 0x80) > 0)
608
609 public Hashtable GetAttachments()
610 {
611 if (m_attachments.Count == 0)
612 return null;
613
614 Hashtable ret = new Hashtable();
615
616 foreach (KeyValuePair<int, AvatarAttachment> kvp in m_attachments)
617 { 631 {
618 Hashtable data = new Hashtable(); 632 // strip the append bit
619 data["item"] = kvp.Value.ItemID.ToString(); 633 int point = attachpoint & 0x7F;
620 data["asset"] = kvp.Value.AssetID.ToString(); 634 AppendAttachment(new AvatarAttachment(point, item, asset));
621 635 }
622 ret[kvp.Key] = data; 636 else
637 {
638 ReplaceAttachment(new AvatarAttachment(attachpoint,item,asset));
623 } 639 }
624
625 return ret;
626 }
627
628 public List<int> GetAttachedPoints()
629 {
630 return new List<int>(m_attachments.Keys);
631 }
632
633 public UUID GetAttachedItem(int attachpoint)
634 {
635 if (!m_attachments.ContainsKey(attachpoint))
636 return UUID.Zero;
637
638 return m_attachments[attachpoint].ItemID;
639 }
640
641 public UUID GetAttachedAsset(int attachpoint)
642 {
643 if (!m_attachments.ContainsKey(attachpoint))
644 return UUID.Zero;
645
646 return m_attachments[attachpoint].AssetID;
647 } 640 }
648 641
649 public int GetAttachpoint(UUID itemID) 642 public int GetAttachpoint(UUID itemID)
650 { 643 {
651 foreach (KeyValuePair<int, AvatarAttachment> kvp in m_attachments) 644 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
652 { 645 {
653 if (kvp.Value.ItemID == itemID) 646 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
654 { 647 if (index >= 0)
655 return kvp.Key; 648 return kvp.Key;
656 }
657 } 649 }
650
658 return 0; 651 return 0;
659 } 652 }
660 653
661 public void DetachAttachment(UUID itemID) 654 public void DetachAttachment(UUID itemID)
662 { 655 {
663 int attachpoint = GetAttachpoint(itemID); 656 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
657 {
658 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
659 if (index >= 0)
660 {
661 // Remove it from the list of attachments at that attach point
662 m_attachments[kvp.Key].RemoveAt(index);
664 663
665 if (attachpoint > 0) 664 // And remove the list if there are no more attachments here
666 m_attachments.Remove(attachpoint); 665 if (m_attachments[kvp.Key].Count == 0)
666 m_attachments.Remove(kvp.Key);
667 return;
668 }
669 }
667 } 670 }
668 671
669 public void ClearAttachments() 672 public void ClearAttachments()
@@ -671,6 +674,8 @@ namespace OpenSim.Framework
671 m_attachments.Clear(); 674 m_attachments.Clear();
672 } 675 }
673 676
677 #region Packing Functions
678
674 /// <summary> 679 /// <summary>
675 /// Create an OSDMap from the appearance data 680 /// Create an OSDMap from the appearance data
676 /// </summary> 681 /// </summary>
@@ -695,7 +700,7 @@ namespace OpenSim.Framework
695 if (m_texture.FaceTextures[i] != null) 700 if (m_texture.FaceTextures[i] != null)
696 textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID)); 701 textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID));
697 else 702 else
698 textures.Add(OSD.FromUUID(UUID.Zero)); 703 textures.Add(OSD.FromUUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
699 } 704 }
700 data["textures"] = textures; 705 data["textures"] = textures;
701 706
@@ -705,8 +710,8 @@ namespace OpenSim.Framework
705 710
706 // Attachments 711 // Attachments
707 OSDArray attachs = new OSDArray(m_attachments.Count); 712 OSDArray attachs = new OSDArray(m_attachments.Count);
708 foreach (KeyValuePair<int, AvatarAttachment> kvp in m_attachments) 713 foreach (AvatarAttachment attach in GetAttachments())
709 attachs.Add(kvp.Value.Pack()); 714 attachs.Add(attach.Pack());
710 data["attachments"] = attachs; 715 data["attachments"] = attachs;
711 716
712 return data; 717 return data;
@@ -718,8 +723,8 @@ namespace OpenSim.Framework
718 /// </summary> 723 /// </summary>
719 public void Unpack(OSDMap data) 724 public void Unpack(OSDMap data)
720 { 725 {
721 if ((data != null) && (data["appearance_serial"] != null)) 726 if ((data != null) && (data["serial"] != null))
722 m_serial = data["appearance_serial"].AsInteger(); 727 m_serial = data["serial"].AsInteger();
723 if ((data != null) && (data["height"] != null)) 728 if ((data != null) && (data["height"] != null))
724 m_avatarHeight = (float)data["height"].AsReal(); 729 m_avatarHeight = (float)data["height"].AsReal();
725 if ((data != null) && (data["hipoffset"] != null)) 730 if ((data != null) && (data["hipoffset"] != null))
@@ -747,12 +752,10 @@ namespace OpenSim.Framework
747 OSDArray textures = (OSDArray)(data["textures"]); 752 OSDArray textures = (OSDArray)(data["textures"]);
748 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT && i < textures.Count; i++) 753 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT && i < textures.Count; i++)
749 { 754 {
755 UUID textureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
750 if (textures[i] != null) 756 if (textures[i] != null)
751 { 757 textureID = textures[i].AsUUID();
752 UUID textureID = textures[i].AsUUID(); 758 m_texture.CreateFace((uint)i).TextureID = new UUID(textureID);
753 if (textureID != UUID.Zero)
754 m_texture.CreateFace((uint)i).TextureID = textureID;
755 }
756 } 759 }
757 } 760 }
758 else 761 else
@@ -773,15 +776,12 @@ namespace OpenSim.Framework
773 } 776 }
774 777
775 // Attachments 778 // Attachments
776 m_attachments = new Dictionary<int, AvatarAttachment>(); 779 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
777 if ((data != null) && (data["attachments"] != null) && (data["attachments"]).Type == OSDType.Array) 780 if ((data != null) && (data["attachments"] != null) && (data["attachments"]).Type == OSDType.Array)
778 { 781 {
779 OSDArray attachs = (OSDArray)(data["attachments"]); 782 OSDArray attachs = (OSDArray)(data["attachments"]);
780 for (int i = 0; i < attachs.Count; i++) 783 for (int i = 0; i < attachs.Count; i++)
781 { 784 AppendAttachment(new AvatarAttachment((OSDMap)attachs[i]));
782 AvatarAttachment attach = new AvatarAttachment((OSDMap)attachs[i]);
783 m_attachments[attach.AttachPoint] = attach;
784 }
785 } 785 }
786 } 786 }
787 catch (Exception e) 787 catch (Exception e)
@@ -790,6 +790,9 @@ namespace OpenSim.Framework
790 } 790 }
791 } 791 }
792 792
793 #endregion
794
795 #region VPElement
793 796
794 /// <summary> 797 /// <summary>
795 /// Viewer Params Array Element for AgentSetAppearance 798 /// Viewer Params Array Element for AgentSetAppearance
@@ -1553,5 +1556,6 @@ namespace OpenSim.Framework
1553 SKIRT_SKIRT_GREEN = 216, 1556 SKIRT_SKIRT_GREEN = 216,
1554 SKIRT_SKIRT_BLUE = 217 1557 SKIRT_SKIRT_BLUE = 217
1555 } 1558 }
1559 #endregion
1556 } 1560 }
1557} 1561}
diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs
index 6b64e12..872de9a 100644
--- a/OpenSim/Framework/Capabilities/Caps.cs
+++ b/OpenSim/Framework/Capabilities/Caps.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using log4net; 33using log4net;
34using Nini.Config;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenSim.Framework.Servers; 36using OpenSim.Framework.Servers;
36using OpenSim.Framework.Servers.HttpServer; 37using OpenSim.Framework.Servers.HttpServer;
@@ -112,6 +113,8 @@ namespace OpenSim.Framework.Capabilities
112 private string m_regionName; 113 private string m_regionName;
113 private object m_fetchLock = new Object(); 114 private object m_fetchLock = new Object();
114 115
116 private bool m_persistBakedTextures = false;
117
115 public bool SSLCaps 118 public bool SSLCaps
116 { 119 {
117 get { return m_httpListener.UseSSL; } 120 get { return m_httpListener.UseSSL; }
@@ -145,6 +148,15 @@ namespace OpenSim.Framework.Capabilities
145 148
146 m_httpListenPort = httpPort; 149 m_httpListenPort = httpPort;
147 150
151 m_persistBakedTextures = false;
152 IConfigSource config = m_Scene.Config;
153 if (config != null)
154 {
155 IConfig sconfig = config.Configs["Startup"];
156 if (sconfig != null)
157 m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures",m_persistBakedTextures);
158 }
159
148 if (httpServer != null && httpServer.UseSSL) 160 if (httpServer != null && httpServer.UseSSL)
149 { 161 {
150 m_httpListenPort = httpServer.SSLPort; 162 m_httpListenPort = httpServer.SSLPort;
@@ -983,7 +995,7 @@ namespace OpenSim.Framework.Capabilities
983 asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_agentID.ToString()); 995 asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_agentID.ToString());
984 asset.Data = data; 996 asset.Data = data;
985 asset.Temporary = true; 997 asset.Temporary = true;
986 asset.Local = true; 998 asset.Local = ! m_persistBakedTextures; // Local assets aren't persisted, non-local are
987 m_assetCache.Store(asset); 999 m_assetCache.Store(asset);
988 } 1000 }
989 1001
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index fdebba3..66487f7 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
31using OpenMetaverse; 33using OpenMetaverse;
32using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
33 35
@@ -310,6 +312,12 @@ namespace OpenSim.Framework
310 // Appearance 312 // Appearance
311 public AvatarAppearance Appearance; 313 public AvatarAppearance Appearance;
312 314
315// DEBUG ON
316 private static readonly ILog m_log =
317 LogManager.GetLogger(
318 MethodBase.GetCurrentMethod().DeclaringType);
319// DEBUG OFF
320
313/* 321/*
314 public byte[] AgentTextures; 322 public byte[] AgentTextures;
315 public byte[] VisualParams; 323 public byte[] VisualParams;
@@ -323,6 +331,10 @@ namespace OpenSim.Framework
323 331
324 public virtual OSDMap Pack() 332 public virtual OSDMap Pack()
325 { 333 {
334// DEBUG ON
335 m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Pack data");
336// DEBUG OFF
337
326 OSDMap args = new OSDMap(); 338 OSDMap args = new OSDMap();
327 args["message_type"] = OSD.FromString("AgentData"); 339 args["message_type"] = OSD.FromString("AgentData");
328 340
@@ -387,31 +399,40 @@ namespace OpenSim.Framework
387 // args["agent_textures"] = textures; 399 // args["agent_textures"] = textures;
388 //} 400 //}
389 401
390/* 402 // The code to pack textures, visuals, wearables and attachments
391 if ((AgentTextures != null) && (AgentTextures.Length > 0)) 403 // should be removed; packed appearance contains the full appearance
392 args["texture_entry"] = OSD.FromBinary(AgentTextures); 404 // This is retained for backward compatibility only
405 if (Appearance.Texture != null)
406 {
407 byte[] rawtextures = Appearance.Texture.GetBytes();
408 args["texture_entry"] = OSD.FromBinary(rawtextures);
409 }
393 410
394 if ((VisualParams != null) && (VisualParams.Length > 0)) 411 if ((Appearance.VisualParams != null) && (Appearance.VisualParams.Length > 0))
395 args["visual_params"] = OSD.FromBinary(VisualParams); 412 args["visual_params"] = OSD.FromBinary(Appearance.VisualParams);
396 413
397 // We might not pass this in all cases... 414 // We might not pass this in all cases...
398 if ((Wearables != null) && (Wearables.Length > 0)) 415 if ((Appearance.Wearables != null) && (Appearance.Wearables.Length > 0))
399 { 416 {
400 OSDArray wears = new OSDArray(Wearables.Length); 417 OSDArray wears = new OSDArray(Appearance.Wearables.Length * 2);
401 foreach (UUID uuid in Wearables) 418 foreach (AvatarWearable awear in Appearance.Wearables)
402 wears.Add(OSD.FromUUID(uuid)); 419 {
420 wears.Add(OSD.FromUUID(awear.ItemID));
421 wears.Add(OSD.FromUUID(awear.AssetID));
422 }
403 args["wearables"] = wears; 423 args["wearables"] = wears;
404 } 424 }
405 425
406 426 List<AvatarAttachment> attachments = Appearance.GetAttachments();
407 if ((Attachments != null) && (Attachments.Length > 0)) 427 if ((attachments != null) && (attachments.Count > 0))
408 { 428 {
409 OSDArray attachs = new OSDArray(Attachments.Length); 429 OSDArray attachs = new OSDArray(attachments.Count);
410 foreach (AvatarAttachment att in Attachments) 430 foreach (AvatarAttachment att in attachments)
411 attachs.Add(att.Pack()); 431 attachs.Add(att.Pack());
412 args["attachments"] = attachs; 432 args["attachments"] = attachs;
413 } 433 }
414*/ 434 // End of code to remove
435
415 if ((Controllers != null) && (Controllers.Length > 0)) 436 if ((Controllers != null) && (Controllers.Length > 0))
416 { 437 {
417 OSDArray controls = new OSDArray(Controllers.Length); 438 OSDArray controls = new OSDArray(Controllers.Length);
@@ -435,6 +456,10 @@ namespace OpenSim.Framework
435 /// <param name="hash"></param> 456 /// <param name="hash"></param>
436 public virtual void Unpack(OSDMap args) 457 public virtual void Unpack(OSDMap args)
437 { 458 {
459// DEBUG ON
460 m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Unpack data");
461// DEBUG OFF
462
438 if (args.ContainsKey("region_id")) 463 if (args.ContainsKey("region_id"))
439 UUID.TryParse(args["region_id"].AsString(), out RegionID); 464 UUID.TryParse(args["region_id"].AsString(), out RegionID);
440 465
@@ -547,41 +572,54 @@ namespace OpenSim.Framework
547 // AgentTextures[i++] = o.AsUUID(); 572 // AgentTextures[i++] = o.AsUUID();
548 //} 573 //}
549 574
550 if (args["packed_appearance"] != null) 575 Appearance = new AvatarAppearance(AgentID);
551 Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); 576
552 else 577 // The code to unpack textures, visuals, wearables and attachments
553 Appearance = new AvatarAppearance(AgentID); 578 // should be removed; packed appearance contains the full appearance
554 579 // This is retained for backward compatibility only
555/*
556 if (args["texture_entry"] != null) 580 if (args["texture_entry"] != null)
557 AgentTextures = args["texture_entry"].AsBinary(); 581 {
582 byte[] rawtextures = args["texture_entry"].AsBinary();
583 Primitive.TextureEntry textures = new Primitive.TextureEntry(rawtextures,0,rawtextures.Length);
584 Appearance.SetTextureEntries(textures);
585 }
558 586
559 if (args["visual_params"] != null) 587 if (args["visual_params"] != null)
560 VisualParams = args["visual_params"].AsBinary(); 588 Appearance.SetVisualParams(args["visual_params"].AsBinary());
561 589
562 if ((args["wearables"] != null) && (args["wearables"]).Type == OSDType.Array) 590 if ((args["wearables"] != null) && (args["wearables"]).Type == OSDType.Array)
563 { 591 {
564 OSDArray wears = (OSDArray)(args["wearables"]); 592 OSDArray wears = (OSDArray)(args["wearables"]);
565 Wearables = new UUID[wears.Count]; 593 for (int i = 0; i < wears.Count / 2; i++)
566 int i = 0; 594 {
567 foreach (OSD o in wears) 595 AvatarWearable awear = new AvatarWearable(wears[i*2].AsUUID(),wears[(i*2)+1].AsUUID());
568 Wearables[i++] = o.AsUUID(); 596 Appearance.SetWearable(i,awear);
597 }
569 } 598 }
570 599
571 if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) 600 if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array)
572 { 601 {
573 OSDArray attachs = (OSDArray)(args["attachments"]); 602 OSDArray attachs = (OSDArray)(args["attachments"]);
574 Attachments = new AvatarAttachment[attachs.Count];
575 int i = 0;
576 foreach (OSD o in attachs) 603 foreach (OSD o in attachs)
577 { 604 {
578 if (o.Type == OSDType.Map) 605 if (o.Type == OSDType.Map)
579 { 606 {
580 Attachments[i++] = new AvatarAttachment((OSDMap)o); 607 // We know all of these must end up as attachments so we
608 // append rather than replace to ensure multiple attachments
609 // per point continues to work
610 Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o));
581 } 611 }
582 } 612 }
583 } 613 }
584*/ 614 // end of code to remove
615
616 if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map)
617 Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]);
618// DEBUG ON
619 else
620 m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance");
621// DEBUG OFF
622
585 if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) 623 if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array)
586 { 624 {
587 OSDArray controls = (OSDArray)(args["controllers"]); 625 OSDArray controls = (OSDArray)(args["controllers"]);
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index ad6b1de..e89368a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -123,15 +123,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
123 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); 123 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
124 124
125 // Save avatar attachment information 125 // Save avatar attachment information
126 ScenePresence presence; 126 m_log.Info(
127 if (m_scene.AvatarService != null && m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 127 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
128 { 128 + ", AttachmentPoint: " + AttachmentPt);
129 m_log.Info(
130 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
131 + ", AttachmentPoint: " + AttachmentPt);
132 129
133 m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance); 130 if (m_scene.AvatarFactory != null)
134 } 131 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
135 } 132 }
136 } 133 }
137 catch (Exception e) 134 catch (Exception e)
@@ -382,8 +379,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
382 item = m_scene.InventoryService.GetItem(item); 379 item = m_scene.InventoryService.GetItem(item);
383 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */); 380 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */);
384 381
385 if (m_scene.AvatarService != null) 382 if (m_scene.AvatarFactory != null)
386 m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance); 383 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
387 } 384 }
388 } 385 }
389 386
@@ -405,11 +402,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
405 presence.Appearance.DetachAttachment(itemID); 402 presence.Appearance.DetachAttachment(itemID);
406 403
407 // Save avatar attachment information 404 // Save avatar attachment information
408 if (m_scene.AvatarService != null) 405 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
409 { 406 if (m_scene.AvatarFactory != null)
410 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); 407 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
411 m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance);
412 }
413 } 408 }
414 409
415 DetachSingleAttachmentToInv(itemID, remoteClient); 410 DetachSingleAttachmentToInv(itemID, remoteClient);
@@ -435,10 +430,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
435 430
436 presence.Appearance.DetachAttachment(itemID); 431 presence.Appearance.DetachAttachment(itemID);
437 432
438 if (m_scene.AvatarService != null) 433 if (m_scene.AvatarFactory != null)
439 { 434 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
440 m_scene.AvatarService.SetAppearance(remoteClient.AgentId, presence.Appearance); 435
441 }
442 part.ParentGroup.DetachToGround(); 436 part.ParentGroup.DetachToGround();
443 437
444 List<UUID> uuids = new List<UUID>(); 438 List<UUID> uuids = new List<UUID>();
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 9f7ff7f..bfbbcf8 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -32,23 +32,45 @@ using Nini.Config;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34 34
35using System.Threading;
36using System.Timers;
37using System.Collections.Generic;
38
35using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
38 42
39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 43namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
40{ 44{
41 public class AvatarFactoryModule : IRegionModule 45 public class AvatarFactoryModule : IAvatarFactory, IRegionModule
42 { 46 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
45 private Scene m_scene = null; 48 private Scene m_scene = null;
46 49
47 private bool m_startAnimationSet = false; 50 private int m_savetime = 5; // seconds to wait before saving changed appearance
51 private int m_sendtime = 2; // seconds to wait before sending changed appearance
52
53 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
54 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
55 private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>();
56 private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>();
48 57
49 public void Initialise(Scene scene, IConfigSource source) 58 #region RegionModule Members
59
60 public void Initialise(Scene scene, IConfigSource config)
50 { 61 {
62 scene.RegisterModuleInterface<IAvatarFactory>(this);
51 scene.EventManager.OnNewClient += NewClient; 63 scene.EventManager.OnNewClient += NewClient;
64
65 if (config != null)
66 {
67 IConfig sconfig = config.Configs["Startup"];
68 if (sconfig != null)
69 {
70 m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
71 m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
72 }
73 }
52 74
53 if (m_scene == null) 75 if (m_scene == null)
54 m_scene = scene; 76 m_scene = scene;
@@ -56,6 +78,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
56 78
57 public void PostInitialise() 79 public void PostInitialise()
58 { 80 {
81 m_updateTimer.Enabled = false;
82 m_updateTimer.AutoReset = true;
83 m_updateTimer.Interval = m_checkTime; // 500 milliseconds wait to start async ops
84 m_updateTimer.Elapsed += new ElapsedEventHandler(HandleAppearanceUpdateTimer);
59 } 85 }
60 86
61 public void Close() 87 public void Close()
@@ -84,6 +110,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
84 // client.OnAvatarNowWearing -= AvatarIsWearing; 110 // client.OnAvatarNowWearing -= AvatarIsWearing;
85 } 111 }
86 112
113 #endregion
114
115 public bool ValidateBakedTextureCache(IClientAPI client)
116 {
117 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
118 if (sp == null)
119 {
120 m_log.WarnFormat("[AVFACTORY] SetAppearance unable to find presence for {0}",client.AgentId);
121 return false;
122 }
123
124 bool cached = true;
125
126 // Process the texture entry
127 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
128 {
129 int idx = AvatarAppearance.BAKE_INDICES[i];
130 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
131 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
132 if (! CheckBakedTextureAsset(client,face.TextureID,idx))
133 {
134 sp.Appearance.Texture.FaceTextures[idx] = null;
135 cached = false;
136 }
137 }
138
139 return cached;
140 }
141
142
87 /// <summary> 143 /// <summary>
88 /// Set appearance data (textureentry and slider settings) received from the client 144 /// Set appearance data (textureentry and slider settings) received from the client
89 /// </summary> 145 /// </summary>
@@ -91,6 +147,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
91 /// <param name="visualParam"></param> 147 /// <param name="visualParam"></param>
92 public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) 148 public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
93 { 149 {
150// DEBUG ON
151 m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId);
152// DEBUG OFF
153
94 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 154 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
95 if (sp == null) 155 if (sp == null)
96 { 156 {
@@ -98,85 +158,179 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
98 return; 158 return;
99 } 159 }
100 160
101// DEBUG ON
102 m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId);
103// DEBUG OFF
104
105/*
106 if (m_physicsActor != null)
107 {
108 if (!IsChildAgent)
109 {
110 // This may seem like it's redundant, remove the avatar from the physics scene
111 // just to add it back again, but it saves us from having to update
112 // 3 variables 10 times a second.
113 bool flyingTemp = m_physicsActor.Flying;
114 RemoveFromPhysicalScene();
115 //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
116
117 //PhysicsActor = null;
118
119 AddToPhysicalScene(flyingTemp);
120 }
121 }
122*/
123 #region Bake Cache Check
124
125 bool changed = false; 161 bool changed = false;
126 162
127 // Process the texture entry 163 // Process the texture entry
128 if (textureEntry != null) 164 if (textureEntry != null)
129 { 165 {
130 for (int i = 0; i < BAKE_INDICES.Length; i++) 166 changed = sp.Appearance.SetTextureEntries(textureEntry);
131 {
132 int j = BAKE_INDICES[i];
133 Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
134 167
168 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
169 {
170 int idx = AvatarAppearance.BAKE_INDICES[i];
171 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
135 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) 172 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
136 { 173 Util.FireAndForget(delegate(object o) {
137 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) 174 if (! CheckBakedTextureAsset(client,face.TextureID,idx))
138 { 175 client.SendRebakeAvatarTextures(face.TextureID);
139 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",face.TextureID,j,this.Name); 176 });
140 client.SendRebakeAvatarTextures(face.TextureID);
141 }
142 }
143 } 177 }
144 changed = sp.Appearance.SetTextureEntries(textureEntry);
145
146 } 178 }
147 179
148 #endregion Bake Cache Check 180 // Process the visual params, this may change height as well
149 181 if (visualParams != null)
150 changed = sp.Appearance.SetVisualParams(visualParams) || changed; 182 {
151 183 if (sp.Appearance.SetVisualParams(visualParams))
152 // If nothing changed (this happens frequently) just return 184 {
185 changed = true;
186 if (sp.Appearance.AvatarHeight > 0)
187 sp.SetHeight(sp.Appearance.AvatarHeight);
188 }
189 }
190
191 // If something changed in the appearance then queue an appearance save
153 if (changed) 192 if (changed)
193 QueueAppearanceSave(client.AgentId);
194
195 // And always queue up an appearance update to send out
196 QueueAppearanceSend(client.AgentId);
197
198 // Send the appearance back to the avatar
199 // AvatarAppearance avp = sp.Appearance;
200 // sp.ControllingClient.SendAvatarDataImmediate(sp);
201 // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
202 }
203
204 /// <summary>
205 /// Checks for the existance of a baked texture asset and
206 /// requests the viewer rebake if the asset is not found
207 /// </summary>
208 /// <param name="client"></param>
209 /// <param name="textureID"></param>
210 /// <param name="idx"></param>
211 private bool CheckBakedTextureAsset(IClientAPI client, UUID textureID, int idx)
212 {
213 if (m_scene.AssetService.Get(textureID.ToString()) == null)
154 { 214 {
215 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",
216 textureID,idx,client.Name);
217 return false;
218 }
219 return true;
220 }
221
222 #region UpdateAppearanceTimer
223
224 public void QueueAppearanceSend(UUID agentid)
225 {
155// DEBUG ON 226// DEBUG ON
156 m_log.Warn("[AVFACTORY] Appearance changed"); 227 m_log.WarnFormat("[AVFACTORY] Queue appearance send for {0}",agentid);
157// DEBUG OFF 228// DEBUG OFF
158 sp.Appearance.SetAppearance(textureEntry, visualParams);
159 if (sp.Appearance.AvatarHeight > 0)
160 sp.SetHeight(sp.Appearance.AvatarHeight);
161 229
162 m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); 230 // 100 nanoseconds (ticks) we should wait
231 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 10000000);
232 lock (m_sendqueue)
233 {
234 m_sendqueue[agentid] = timestamp;
235 m_updateTimer.Start();
163 } 236 }
237 }
238
239 public void QueueAppearanceSave(UUID agentid)
240 {
164// DEBUG ON 241// DEBUG ON
165 else 242 m_log.WarnFormat("[AVFACTORY] Queue appearance save for {0}",agentid);
166 m_log.Warn("[AVFACTORY] Appearance did not change"); 243// DEBUG OFF
167// DEBUG OFF
168 244
245 // 100 nanoseconds (ticks) we should wait
246 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 10000000);
247 lock (m_savequeue)
248 {
249 m_savequeue[agentid] = timestamp;
250 m_updateTimer.Start();
251 }
252 }
253
254 private void HandleAppearanceSend(UUID agentid)
255 {
256 ScenePresence sp = m_scene.GetScenePresence(agentid);
257 if (sp == null)
258 {
259 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
260 return;
261 }
262
263// DEBUG ON
264 m_log.WarnFormat("[AVFACTORY] Handle appearance send for {0}",agentid);
265// DEBUG OFF
266
267 // Send the appearance to everyone in the scene
169 sp.SendAppearanceToAllOtherAgents(); 268 sp.SendAppearanceToAllOtherAgents();
269 sp.ControllingClient.SendAvatarDataImmediate(sp);
270
271 // Send the appearance back to the avatar
272 // AvatarAppearance avp = sp.Appearance;
273 // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
274
275/*
276// this needs to be fixed, the flag should be on scene presence not the region module
277 // Start the animations if necessary
170 if (!m_startAnimationSet) 278 if (!m_startAnimationSet)
171 { 279 {
172 sp.Animator.UpdateMovementAnimations(); 280 sp.Animator.UpdateMovementAnimations();
173 m_startAnimationSet = true; 281 m_startAnimationSet = true;
174 } 282 }
283*/
284 }
175 285
176 client.SendAvatarDataImmediate(sp); 286 private void HandleAppearanceSave(UUID agentid)
177 client.SendAppearance(sp.Appearance.Owner,sp.Appearance.VisualParams,sp.Appearance.Texture.GetBytes()); 287 {
288 ScenePresence sp = m_scene.GetScenePresence(agentid);
289 if (sp == null)
290 {
291 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
292 return;
293 }
294
295 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
178 } 296 }
179 297
298 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
299 {
300 long now = DateTime.Now.Ticks;
301
302 lock (m_sendqueue)
303 {
304 Dictionary<UUID,long> sends = new Dictionary<UUID,long>(m_sendqueue);
305 foreach (KeyValuePair<UUID,long> kvp in sends)
306 {
307 if (kvp.Value < now)
308 {
309 Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); });
310 m_sendqueue.Remove(kvp.Key);
311 }
312 }
313 }
314
315 lock (m_savequeue)
316 {
317 Dictionary<UUID,long> saves = new Dictionary<UUID,long>(m_savequeue);
318 foreach (KeyValuePair<UUID,long> kvp in saves)
319 {
320 if (kvp.Value < now)
321 {
322 Util.FireAndForget(delegate(object o) { HandleAppearanceSave(kvp.Key); });
323 m_savequeue.Remove(kvp.Key);
324 }
325 }
326 }
327
328 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
329 m_updateTimer.Stop();
330 }
331
332 #endregion
333
180 /// <summary> 334 /// <summary>
181 /// Tell the client for this scene presence what items it should be wearing now 335 /// Tell the client for this scene presence what items it should be wearing now
182 /// </summary> 336 /// </summary>
@@ -215,14 +369,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
215 369
216 AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance); 370 AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance);
217 371
218 //if (!TryGetAvatarAppearance(client.AgentId, out avatAppearance))
219 //{
220 // m_log.Warn("[AVFACTORY]: We didn't seem to find the appearance, falling back to ScenePresence");
221 // avatAppearance = sp.Appearance;
222 //}
223
224 //m_log.DebugFormat("[AVFACTORY]: Received wearables for {0}", client.Name);
225
226 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 372 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
227 { 373 {
228 if (wear.Type < AvatarWearable.MAX_WEARABLES) 374 if (wear.Type < AvatarWearable.MAX_WEARABLES)
@@ -232,10 +378,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
232 } 378 }
233 } 379 }
234 380
381 // This could take awhile since it needs to pull inventory
235 SetAppearanceAssets(sp.UUID, ref avatAppearance); 382 SetAppearanceAssets(sp.UUID, ref avatAppearance);
236 383
237 m_scene.AvatarService.SetAppearance(client.AgentId, avatAppearance);
238 sp.Appearance = avatAppearance; 384 sp.Appearance = avatAppearance;
385 m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance);
239 } 386 }
240 387
241 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) 388 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance)
diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs
new file mode 100644
index 0000000..22795fc
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs
@@ -0,0 +1,39 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29using OpenSim.Framework;
30
31namespace OpenSim.Region.Framework.Interfaces
32{
33 public interface IAvatarFactory
34 {
35 bool ValidateBakedTextureCache(IClientAPI client);
36 void QueueAppearanceSend(UUID agentid);
37 void QueueAppearanceSave(UUID agentid);
38 }
39}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 6367fcf..3343d08 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -119,6 +119,7 @@ namespace OpenSim.Region.Framework.Scenes
119 119
120 protected IXMLRPC m_xmlrpcModule; 120 protected IXMLRPC m_xmlrpcModule;
121 protected IWorldComm m_worldCommModule; 121 protected IWorldComm m_worldCommModule;
122 protected IAvatarFactory m_AvatarFactory;
122 protected IConfigSource m_config; 123 protected IConfigSource m_config;
123 protected IRegionSerialiserModule m_serialiser; 124 protected IRegionSerialiserModule m_serialiser;
124 protected IDialogModule m_dialogModule; 125 protected IDialogModule m_dialogModule;
@@ -398,6 +399,11 @@ namespace OpenSim.Region.Framework.Scenes
398 399
399 public IAttachmentsModule AttachmentsModule { get; set; } 400 public IAttachmentsModule AttachmentsModule { get; set; }
400 401
402 public IAvatarFactory AvatarFactory
403 {
404 get { return m_AvatarFactory; }
405 }
406
401 public ICapabilitiesModule CapsModule 407 public ICapabilitiesModule CapsModule
402 { 408 {
403 get { return m_capsModule; } 409 get { return m_capsModule; }
@@ -1153,6 +1159,7 @@ namespace OpenSim.Region.Framework.Scenes
1153 m_xmlrpcModule = RequestModuleInterface<IXMLRPC>(); 1159 m_xmlrpcModule = RequestModuleInterface<IXMLRPC>();
1154 m_worldCommModule = RequestModuleInterface<IWorldComm>(); 1160 m_worldCommModule = RequestModuleInterface<IWorldComm>();
1155 XferManager = RequestModuleInterface<IXfer>(); 1161 XferManager = RequestModuleInterface<IXfer>();
1162 m_AvatarFactory = RequestModuleInterface<IAvatarFactory>();
1156 AttachmentsModule = RequestModuleInterface<IAttachmentsModule>(); 1163 AttachmentsModule = RequestModuleInterface<IAttachmentsModule>();
1157 m_serialiser = RequestModuleInterface<IRegionSerialiserModule>(); 1164 m_serialiser = RequestModuleInterface<IRegionSerialiserModule>();
1158 m_dialogModule = RequestModuleInterface<IDialogModule>(); 1165 m_dialogModule = RequestModuleInterface<IDialogModule>();
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 6576e64..9402f8b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -704,20 +704,14 @@ namespace OpenSim.Region.Framework.Scenes
704 // we created a new ScenePresence (a new child agent) in a fresh region. 704 // we created a new ScenePresence (a new child agent) in a fresh region.
705 // Request info about all the (root) agents in this region 705 // Request info about all the (root) agents in this region
706 // Note: This won't send data *to* other clients in that region (children don't send) 706 // Note: This won't send data *to* other clients in that region (children don't send)
707
708// MIC: This gets called again in CompleteMovement
707 SendInitialFullUpdateToAllClients(); 709 SendInitialFullUpdateToAllClients();
708 710
709 RegisterToEvents(); 711 RegisterToEvents();
710 SetDirectionVectors(); 712 SetDirectionVectors();
711 } 713 }
712 714
713/*
714 public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
715 AvatarWearable[] wearables)
716 : this(client, world, reginfo)
717 {
718 m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
719 }
720*/
721 public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) 715 public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
722 : this(client, world, reginfo) 716 : this(client, world, reginfo)
723 { 717 {
@@ -1081,7 +1075,9 @@ namespace OpenSim.Region.Framework.Scenes
1081 /// </summary> 1075 /// </summary>
1082 public void CompleteMovement(IClientAPI client) 1076 public void CompleteMovement(IClientAPI client)
1083 { 1077 {
1084 //m_log.Debug("[SCENE PRESENCE]: CompleteMovement"); 1078// DEBUG ON
1079 m_log.WarnFormat("[SCENE PRESENCE]: CompleteMovement for {0}",UUID);
1080// DEBUG OFF
1085 1081
1086 Vector3 look = Velocity; 1082 Vector3 look = Velocity;
1087 if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1083 if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
@@ -2381,12 +2377,20 @@ namespace OpenSim.Region.Framework.Scenes
2381 // 2 stage check is needed. 2377 // 2 stage check is needed.
2382 if (remoteAvatar == null) 2378 if (remoteAvatar == null)
2383 return; 2379 return;
2380
2384 IClientAPI cl=remoteAvatar.ControllingClient; 2381 IClientAPI cl=remoteAvatar.ControllingClient;
2385 if (cl == null) 2382 if (cl == null)
2386 return; 2383 return;
2384
2387 if (m_appearance.Texture == null) 2385 if (m_appearance.Texture == null)
2388 return; 2386 return;
2389 2387
2388 if (LocalId == remoteAvatar.LocalId)
2389 {
2390 m_log.WarnFormat("[SP] An agent is attempting to send data to itself; {0}",UUID);
2391 return;
2392 }
2393
2390 if (IsChildAgent) 2394 if (IsChildAgent)
2391 { 2395 {
2392 m_log.WarnFormat("[SCENEPRESENCE] A child agent is attempting to send out avatar data"); 2396 m_log.WarnFormat("[SCENEPRESENCE] A child agent is attempting to send out avatar data");
@@ -2407,20 +2411,23 @@ namespace OpenSim.Region.Framework.Scenes
2407 m_scene.ForEachScenePresence(delegate(ScenePresence avatar) 2411 m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
2408 { 2412 {
2409 ++avUpdates; 2413 ++avUpdates;
2410 // only send if this is the root (children are only "listening posts" in a foreign region) 2414
2415 // Don't update ourselves
2416 if (avatar.LocalId == LocalId)
2417 return;
2418
2419 // If this is a root agent, then get info about the avatar
2411 if (!IsChildAgent) 2420 if (!IsChildAgent)
2412 { 2421 {
2413 SendFullUpdateToOtherClient(avatar); 2422 SendFullUpdateToOtherClient(avatar);
2414 } 2423 }
2415 2424
2416 if (avatar.LocalId != LocalId) 2425 // If the other avatar is a root
2426 if (!avatar.IsChildAgent)
2417 { 2427 {
2418 if (!avatar.IsChildAgent) 2428 avatar.SendFullUpdateToOtherClient(this);
2419 { 2429 avatar.SendAppearanceToOtherAgent(this);
2420 avatar.SendFullUpdateToOtherClient(this); 2430 avatar.Animator.SendAnimPackToClient(ControllingClient);
2421 avatar.SendAppearanceToOtherAgent(this);
2422 avatar.Animator.SendAnimPackToClient(ControllingClient);
2423 }
2424 } 2431 }
2425 }); 2432 });
2426 2433
@@ -2465,7 +2472,19 @@ namespace OpenSim.Region.Framework.Scenes
2465 // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); 2472 // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
2466 2473
2467 m_controllingClient.SendAvatarDataImmediate(this); 2474 m_controllingClient.SendAvatarDataImmediate(this);
2468 m_controllingClient.SendAppearance(m_appearance.Owner,m_appearance.VisualParams,m_appearance.Texture.GetBytes()); 2475 if (m_scene.AvatarFactory != null)
2476 {
2477 if (m_scene.AvatarFactory.ValidateBakedTextureCache(m_controllingClient))
2478 {
2479 m_log.WarnFormat("[SP] baked textures are in the ache for {0}",Name);
2480 m_controllingClient.SendAppearance(
2481 m_appearance.Owner,m_appearance.VisualParams,m_appearance.Texture.GetBytes());
2482 }
2483 }
2484 else
2485 {
2486 m_log.WarnFormat("[SP] AvatarFactory not set");
2487 }
2469 2488
2470 SendInitialFullUpdateToAllClients(); 2489 SendInitialFullUpdateToAllClients();
2471 } 2490 }
@@ -2497,9 +2516,16 @@ namespace OpenSim.Region.Framework.Scenes
2497 /// <param name="avatar"></param> 2516 /// <param name="avatar"></param>
2498 public void SendAppearanceToOtherAgent(ScenePresence avatar) 2517 public void SendAppearanceToOtherAgent(ScenePresence avatar)
2499 { 2518 {
2519 if (LocalId == avatar.LocalId)
2520 {
2521 m_log.WarnFormat("[SP] An agent is attempting to send data to itself; {0}",UUID);
2522 return;
2523 }
2524
2500// DEBUG ON 2525// DEBUG ON
2501 m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); 2526// m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId);
2502// DEBUG OFF 2527// DEBUG OFF
2528
2503 avatar.ControllingClient.SendAppearance( 2529 avatar.ControllingClient.SendAppearance(
2504 m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); 2530 m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
2505 } 2531 }
@@ -3656,15 +3682,16 @@ namespace OpenSim.Region.Framework.Scenes
3656 return; 3682 return;
3657 } 3683 }
3658 3684
3659 List<int> attPoints = m_appearance.GetAttachedPoints(); 3685 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3660 foreach (int p in attPoints) 3686 foreach (AvatarAttachment attach in attachments)
3661 { 3687 {
3662 if (m_isDeleted) 3688 if (m_isDeleted)
3663 return; 3689 return;
3664 3690
3665 UUID itemID = m_appearance.GetAttachedItem(p); 3691 int p = attach.AttachPoint;
3692 UUID itemID = attach.ItemID;
3666 3693
3667 //UUID assetID = m_appearance.GetAttachedAsset(p); 3694 //UUID assetID = attach.AssetID;
3668 // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down 3695 // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
3669 // But they're not used anyway, the item is being looked up for now, so let's proceed. 3696 // But they're not used anyway, the item is being looked up for now, so let's proceed.
3670 //if (UUID.Zero == assetID) 3697 //if (UUID.Zero == assetID)
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs
index 0786bd9..922eaaf 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs
@@ -29,6 +29,7 @@ using System.Collections;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Security; 30using System.Security;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
34 35
@@ -81,16 +82,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
81 get { 82 get {
82 List<IAvatarAttachment> attachments = new List<IAvatarAttachment>(); 83 List<IAvatarAttachment> attachments = new List<IAvatarAttachment>();
83 84
84 Hashtable internalAttachments = GetSP().Appearance.GetAttachments(); 85 List<AvatarAttachment> internalAttachments = GetSP().Appearance.GetAttachments();
85 if (internalAttachments != null) 86 foreach (AvatarAttachment attach in internalAttachments)
86 { 87 {
87 foreach (DictionaryEntry element in internalAttachments) 88 attachments.Add(new SPAvatarAttachment(m_rootScene, this, attach.AttachPoint,
88 { 89 new UUID(attach.ItemID),
89 Hashtable attachInfo = (Hashtable)element.Value; 90 new UUID(attach.AssetID), m_security));
90 attachments.Add(new SPAvatarAttachment(m_rootScene, this, (int) element.Key,
91 new UUID((string) attachInfo["item"]),
92 new UUID((string) attachInfo["asset"]), m_security));
93 }
94 } 91 }
95 92
96 return attachments.ToArray(); 93 return attachments.ToArray();
diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs
index 93b977b..eaa6534 100644
--- a/OpenSim/Services/Interfaces/IAvatarService.cs
+++ b/OpenSim/Services/Interfaces/IAvatarService.cs
@@ -178,17 +178,11 @@ namespace OpenSim.Services.Interfaces
178 Data["UnderShirtAsset"] = appearance.UnderShirtAsset.ToString(); 178 Data["UnderShirtAsset"] = appearance.UnderShirtAsset.ToString();
179 179
180 // Attachments 180 // Attachments
181 Hashtable attachs = appearance.GetAttachments(); 181 List<AvatarAttachment> attachments = appearance.GetAttachments();
182 if (attachs != null) 182 foreach (AvatarAttachment attach in attachments)
183 foreach (DictionaryEntry dentry in attachs) 183 {
184 { 184 Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
185 if (dentry.Value != null) 185 }
186 {
187 Hashtable tab = (Hashtable)dentry.Value;
188 if (tab.ContainsKey("item") && tab["item"] != null)
189 Data["_ap_" + dentry.Key] = tab["item"].ToString();
190 }
191 }
192 } 186 }
193 187
194 public AvatarAppearance ToAvatarAppearance(UUID owner) 188 public AvatarAppearance ToAvatarAppearance(UUID owner)
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 82267ed..5ced7d5 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -255,6 +255,20 @@
255 ; OpenJPEG if false 255 ; OpenJPEG if false
256 ; UseCSJ2K = true 256 ; UseCSJ2K = true
257 257
258 ; Persist avatar baked textures
259 ; Persisting baked textures can speed up login and region border
260 ; crossings especially with large numbers of users, though it
261 ; will store potentially large numbers of textures in your asset
262 ; database
263 PersistBakedTextures = false
264
265 ; Control the delay before appearance is sent to other avatars and
266 ; saved in the avatar service. Attempts to limit the impact caused
267 ; by the very chatty dialog that sets appearance when an avatar
268 ; logs in or teleports into a region; values are in seconds
269 DelayBeforeAppearanceSave = 5
270 DelayBeforeAppearanceSend = 2
271
258[SMTP] 272[SMTP]
259 enabled=false 273 enabled=false
260 274