diff options
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs | 8 | ||||
-rw-r--r-- | OpenSim/ApplicationPlugins/Rest/Inventory/RestAppearanceServices.cs | 25 | ||||
-rw-r--r-- | OpenSim/Framework/AgentCircuitData.cs | 66 | ||||
-rw-r--r-- | OpenSim/Framework/AvatarAppearance.cs | 186 | ||||
-rw-r--r-- | OpenSim/Framework/Capabilities/Caps.cs | 14 | ||||
-rw-r--r-- | OpenSim/Framework/ChildAgentDataUpdate.cs | 98 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 32 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 277 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Interfaces/IAvatarFactory.cs | 39 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 7 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 73 | ||||
-rw-r--r-- | OpenSim/Region/OptionalModules/Scripting/Minimodule/SPAvatar.cs | 15 | ||||
-rw-r--r-- | OpenSim/Services/Interfaces/IAvatarService.cs | 16 |
13 files changed, 553 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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | ||
30 | using System.Xml; | 31 | using System.Xml; |
31 | using OpenMetaverse; | 32 | using OpenMetaverse; |
32 | using OpenSim.Framework; | 33 | using 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; | |||
31 | using System.IO; | 31 | using System.IO; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | using log4net; | 33 | using log4net; |
34 | using Nini.Config; | ||
34 | using OpenMetaverse; | 35 | using OpenMetaverse; |
35 | using OpenSim.Framework.Servers; | 36 | using OpenSim.Framework.Servers; |
36 | using OpenSim.Framework.Servers.HttpServer; | 37 | using 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 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | ||
32 | using log4net; | ||
31 | using OpenMetaverse; | 33 | using OpenMetaverse; |
32 | using OpenMetaverse.StructuredData; | 34 | using 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; | |||
32 | using OpenMetaverse; | 32 | using OpenMetaverse; |
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | 34 | ||
35 | using System.Threading; | ||
36 | using System.Timers; | ||
37 | using System.Collections.Generic; | ||
38 | |||
35 | using OpenSim.Region.Framework.Interfaces; | 39 | using OpenSim.Region.Framework.Interfaces; |
36 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
37 | using OpenSim.Services.Interfaces; | 41 | using OpenSim.Services.Interfaces; |
38 | 42 | ||
39 | namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | 43 | namespace 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 | |||
28 | using OpenMetaverse; | ||
29 | using OpenSim.Framework; | ||
30 | |||
31 | namespace 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; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Security; | 30 | using System.Security; |
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenSim.Framework; | ||
32 | using OpenSim.Region.Framework.Scenes; | 33 | using OpenSim.Region.Framework.Scenes; |
33 | using OpenSim.Region.Framework.Interfaces; | 34 | using 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) |