aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs17
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs83
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs4
-rw-r--r--OpenSim/Services/Interfaces/IAvatarService.cs21
9 files changed, 94 insertions, 49 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index bb8825b..ee96b47 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -108,6 +108,7 @@ namespace OpenSim.Framework.Servers.HttpServer
108 private int _bufferLength; 108 private int _bufferLength;
109 private bool _closing; 109 private bool _closing;
110 private bool _upgraded; 110 private bool _upgraded;
111 private int _maxPayloadBytes = 41943040;
111 112
112 private const string HandshakeAcceptText = 113 private const string HandshakeAcceptText =
113 "HTTP/1.1 101 Switching Protocols\r\n" + 114 "HTTP/1.1 101 Switching Protocols\r\n" +
@@ -196,6 +197,15 @@ namespace OpenSim.Framework.Servers.HttpServer
196 } 197 }
197 198
198 /// <summary> 199 /// <summary>
200 /// Max Payload Size in bytes. Defaults to 40MB, but could be set upon connection before calling handshake and upgrade.
201 /// </summary>
202 public int MaxPayloadSize
203 {
204 get { return _maxPayloadBytes; }
205 set { _maxPayloadBytes = value; }
206 }
207
208 /// <summary>
199 /// This triggers the websocket start the upgrade process 209 /// This triggers the websocket start the upgrade process
200 /// </summary> 210 /// </summary>
201 public void HandshakeAndUpgrade() 211 public void HandshakeAndUpgrade()
@@ -367,7 +377,12 @@ namespace OpenSim.Framework.Servers.HttpServer
367 if (headerread) 377 if (headerread)
368 { 378 {
369 _socketState.FrameComplete = false; 379 _socketState.FrameComplete = false;
370 380 if (pheader.PayloadLen > (ulong) _maxPayloadBytes)
381 {
382 Close("Invalid Payload size");
383
384 return;
385 }
371 if (pheader.PayloadLen > 0) 386 if (pheader.PayloadLen > 0)
372 { 387 {
373 if ((int) pheader.PayloadLen > _bufferPosition - offset) 388 if ((int) pheader.PayloadLen > _bufferPosition - offset)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 5675870..6742d99 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -790,7 +790,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
790 handshake.RegionInfo3.ColoName = Utils.EmptyBytes; 790 handshake.RegionInfo3.ColoName = Utils.EmptyBytes;
791 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 791 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
792 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 792 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
793 793 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[0];
794
794 OutPacket(handshake, ThrottleOutPacketType.Task); 795 OutPacket(handshake, ThrottleOutPacketType.Task);
795 } 796 }
796 797
@@ -3571,6 +3572,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3571 3572
3572 avp.Sender.IsTrial = false; 3573 avp.Sender.IsTrial = false;
3573 avp.Sender.ID = agentID; 3574 avp.Sender.ID = agentID;
3575 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
3574 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); 3576 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3575 OutPacket(avp, ThrottleOutPacketType.Task); 3577 OutPacket(avp, ThrottleOutPacketType.Task);
3576 } 3578 }
@@ -4192,7 +4194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4192 pack.Stat = stats.StatsBlock; 4194 pack.Stat = stats.StatsBlock;
4193 4195
4194 pack.Header.Reliable = false; 4196 pack.Header.Reliable = false;
4195 4197 pack.RegionInfo = new SimStatsPacket.RegionInfoBlock[0];
4196 OutPacket(pack, ThrottleOutPacketType.Task); 4198 OutPacket(pack, ThrottleOutPacketType.Task);
4197 } 4199 }
4198 4200
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 3ccf9f4..ab7e932 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -221,9 +221,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
221 // If we're an NPC then skip all the item checks and manipulations since we don't have an 221 // If we're an NPC then skip all the item checks and manipulations since we don't have an
222 // inventory right now. 222 // inventory right now.
223 if (sp.PresenceType == PresenceType.Npc) 223 if (sp.PresenceType == PresenceType.Npc)
224 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p); 224 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, true);
225 else 225 else
226 RezSingleAttachmentFromInventory(sp, attach.ItemID, p); 226 RezSingleAttachmentFromInventory(sp, attach.ItemID, p | (uint)0x80);
227 } 227 }
228 catch (Exception e) 228 catch (Exception e)
229 { 229 {
@@ -283,13 +283,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
283 283
284 sp.ClearAttachments(); 284 sp.ClearAttachments();
285 } 285 }
286 286
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool append)
288 { 288 {
289 if (!Enabled) 289 if (!Enabled)
290 return false; 290 return false;
291 291
292 if (AttachObjectInternal(sp, group, attachmentPt, silent, temp)) 292 if (AttachObjectInternal(sp, group, attachmentPt, silent, temp, append))
293 { 293 {
294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); 294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
295 return true; 295 return true;
@@ -298,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
298 return false; 298 return false;
299 } 299 }
300 300
301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) 301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool append)
302 { 302 {
303// m_log.DebugFormat( 303// m_log.DebugFormat(
304// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", 304// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
@@ -313,7 +313,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
313 return false; 313 return false;
314 } 314 }
315 315
316 if (sp.GetAttachments(attachmentPt).Contains(group)) 316 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
317 if (attachments.Contains(group))
317 { 318 {
318// m_log.WarnFormat( 319// m_log.WarnFormat(
319// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", 320// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
@@ -322,22 +323,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
322 return false; 323 return false;
323 } 324 }
324 325
325 // Remove any previous attachments 326 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
326 List<SceneObjectGroup> existingAttachments = sp.GetAttachments(attachmentPt); 327 while (attachments.Count >= 5)
327 string existingAttachmentScriptState = null; 328 {
329 if (attachments[0].FromItemID != UUID.Zero)
330 DetachSingleAttachmentToInv(sp, attachments[0]);
331 attachments.RemoveAt(0);
332 }
328 333
329 // At the moment we can only deal with a single attachment 334 // If we're not appending, remove the rest as well
330 if (existingAttachments.Count != 0 && existingAttachments[0].FromItemID != UUID.Zero) 335 if (attachments.Count != 0 && !append)
331 DetachSingleAttachmentToInv(sp, group); 336 {
337 foreach (SceneObjectGroup g in attachments)
338 {
339 if (g.FromItemID != UUID.Zero)
340 DetachSingleAttachmentToInv(sp, g);
341 }
342 }
332 343
333 lock (sp.AttachmentsSyncLock) 344 lock (sp.AttachmentsSyncLock)
334 { 345 {
335 Vector3 attachPos = group.AbsolutePosition; 346 Vector3 attachPos = group.AbsolutePosition;
336
337 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
338 // be removed when that functionality is implemented in opensim
339 attachmentPt &= 0x7f;
340
341 // If the attachment point isn't the same as the one previously used 347 // If the attachment point isn't the same as the one previously used
342 // set it's offset position = 0 so that it appears on the attachment point 348 // set it's offset position = 0 so that it appears on the attachment point
343 // and not in a weird location somewhere unknown. 349 // and not in a weird location somewhere unknown.
@@ -365,16 +371,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
365 group.AbsolutePosition = attachPos; 371 group.AbsolutePosition = attachPos;
366 372
367 if (sp.PresenceType != PresenceType.Npc) 373 if (sp.PresenceType != PresenceType.Npc)
368 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp); 374 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append);
369 375
370 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 376 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
371 } 377 }
372 378
373 return true; 379 return true;
374 } 380 }
375 381
376 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp) 382 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp, bool append)
377 { 383 {
384 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
385
378 // Add the new attachment to inventory if we don't already have it. 386 // Add the new attachment to inventory if we don't already have it.
379 if (!temp) 387 if (!temp)
380 { 388 {
@@ -382,7 +390,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
382 if (newAttachmentItemID == UUID.Zero) 390 if (newAttachmentItemID == UUID.Zero)
383 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; 391 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
384 392
385 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 393 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
386 } 394 }
387 } 395 }
388 396
@@ -395,8 +403,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
395// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", 403// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
396// (AttachmentPoint)AttachmentPt, itemID, sp.Name); 404// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
397 405
398 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 406 bool append = (AttachmentPt & 0x80) != 0;
399 // be removed when that functionality is implemented in opensim
400 AttachmentPt &= 0x7f; 407 AttachmentPt &= 0x7f;
401 408
402 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). 409 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
@@ -425,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
425 return null; 432 return null;
426 } 433 }
427 434
428 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); 435 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append);
429 } 436 }
430 437
431 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 438 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -821,8 +828,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
821 so.RemoveScriptInstances(true); 828 so.RemoveScriptInstances(true);
822 } 829 }
823 830
824 private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 831 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
825 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt) 832 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append)
826 { 833 {
827 if (m_invAccessModule == null) 834 if (m_invAccessModule == null)
828 return null; 835 return null;
@@ -875,7 +882,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
875 // This will throw if the attachment fails 882 // This will throw if the attachment fails
876 try 883 try
877 { 884 {
878 AttachObjectInternal(sp, objatt, attachmentPt, false, false); 885 AttachObjectInternal(sp, objatt, attachmentPt, false, false, append);
879 } 886 }
880 catch (Exception e) 887 catch (Exception e)
881 { 888 {
@@ -911,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
911 /// <param name="AttachmentPt"></param> 918 /// <param name="AttachmentPt"></param>
912 /// <param name="itemID"></param> 919 /// <param name="itemID"></param>
913 /// <param name="att"></param> 920 /// <param name="att"></param>
914 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) 921 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att, bool append)
915 { 922 {
916// m_log.DebugFormat( 923// m_log.DebugFormat(
917// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", 924// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
@@ -934,7 +941,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
934 if (item == null) 941 if (item == null)
935 return; 942 return;
936 943
937 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 944 int attFlag = append ? 0x80 : 0;
945 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
938 if (changed && m_scene.AvatarFactory != null) 946 if (changed && m_scene.AvatarFactory != null)
939 { 947 {
940// m_log.DebugFormat( 948// m_log.DebugFormat(
@@ -1018,12 +1026,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1018 return; 1026 return;
1019 } 1027 }
1020 1028
1021 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 1029 bool append = (AttachmentPt & 0x80) != 0;
1022 // be removed when that functionality is implemented in opensim
1023 AttachmentPt &= 0x7f; 1030 AttachmentPt &= 0x7f;
1024 1031
1025 // Calls attach with a Zero position 1032 // Calls attach with a Zero position
1026 AttachObject(sp, part.ParentGroup, AttachmentPt, false, false); 1033 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, append))
1034 {
1035// m_log.Debug(
1036// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
1037// + ", AttachmentPoint: " + AttachmentPt);
1038
1039 // Save avatar attachment information
1040 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
1041 }
1027 } 1042 }
1028 catch (Exception e) 1043 catch (Exception e)
1029 { 1044 {
@@ -1076,4 +1091,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1076 1091
1077 #endregion 1092 #endregion
1078 } 1093 }
1079} \ No newline at end of file 1094}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 0ee01c7..f48bb6f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -197,7 +197,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
198 198
199 m_numberOfAttachEventsFired = 0; 199 m_numberOfAttachEventsFired = 0;
200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
201 201
202 // Check status on scene presence 202 // Check status on scene presence
203 Assert.That(sp.HasAttachments(), Is.True); 203 Assert.That(sp.HasAttachments(), Is.True);
@@ -254,7 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
254 sp2.AbsolutePosition = new Vector3(0, 0, 0); 254 sp2.AbsolutePosition = new Vector3(0, 0, 0);
255 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 255 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
256 256
257 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 257 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
258 258
259 Assert.That(sp.HasAttachments(), Is.False); 259 Assert.That(sp.HasAttachments(), Is.False);
260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -663,4 +663,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
664 } 664 }
665 } 665 }
666} \ No newline at end of file 666}
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 620ec22..46daab3 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -83,7 +83,7 @@ namespace OpenSim.Region.Framework.Interfaces
83 /// <param name="AttachmentPt"></param> 83 /// <param name="AttachmentPt"></param>
84 /// <param name="silent"></param> 84 /// <param name="silent"></param>
85 /// <returns>true if the object was successfully attached, false otherwise</returns> 85 /// <returns>true if the object was successfully attached, false otherwise</returns>
86 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool temp); 86 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool temp, bool append);
87 87
88 /// <summary> 88 /// <summary>
89 /// Rez an attachment from user inventory and change inventory status to match. 89 /// Rez an attachment from user inventory and change inventory status to match.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 14dac7a..3c91c5b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2741,7 +2741,7 @@ namespace OpenSim.Region.Framework.Scenes
2741 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2741 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2742 2742
2743 if (AttachmentsModule != null) 2743 if (AttachmentsModule != null)
2744 AttachmentsModule.AttachObject(sp, grp, 0, false, false); 2744 AttachmentsModule.AttachObject(sp, grp, 0, false, false, true);
2745 } 2745 }
2746 else 2746 else
2747 { 2747 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
index 1e7bc02..e9ddbbe 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); 183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
184 } 184 }
185 185
186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true) ? 1 : 0; 186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0;
187 } 187 }
188 } 188 }
189} 189}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ab087af..cf6f13e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2985,7 +2985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2985 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 2985 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
2986 2986
2987 if (attachmentsModule != null) 2987 if (attachmentsModule != null)
2988 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, false); 2988 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true);
2989 else 2989 else
2990 return false; 2990 return false;
2991 } 2991 }
@@ -11787,4 +11787,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11787 } 11787 }
11788 } 11788 }
11789 } 11789 }
11790} \ No newline at end of file 11790}
diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs
index 863fd93..6ca0b15 100644
--- a/OpenSim/Services/Interfaces/IAvatarService.cs
+++ b/OpenSim/Services/Interfaces/IAvatarService.cs
@@ -174,11 +174,18 @@ namespace OpenSim.Services.Interfaces
174 174
175 // Attachments 175 // Attachments
176 List<AvatarAttachment> attachments = appearance.GetAttachments(); 176 List<AvatarAttachment> attachments = appearance.GetAttachments();
177 Dictionary<int, List<string>> atts = new Dictionary<int, List<string>>();
177 foreach (AvatarAttachment attach in attachments) 178 foreach (AvatarAttachment attach in attachments)
178 { 179 {
179 if (attach.ItemID != UUID.Zero) 180 if (attach.ItemID != UUID.Zero)
180 Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); 181 {
182 if (!atts.ContainsKey(attach.AttachPoint))
183 atts[attach.AttachPoint] = new List<string>();
184 atts[attach.AttachPoint].Add(attach.ItemID.ToString());
185 }
181 } 186 }
187 foreach (KeyValuePair<int, List<string>> kvp in atts)
188 Data["_ap_" + kvp.Key] = string.Join(",", kvp.Value.ToArray());
182 } 189 }
183 190
184 public AvatarAppearance ToAvatarAppearance() 191 public AvatarAppearance ToAvatarAppearance()
@@ -304,10 +311,16 @@ namespace OpenSim.Services.Interfaces
304 if (!Int32.TryParse(pointStr, out point)) 311 if (!Int32.TryParse(pointStr, out point))
305 continue; 312 continue;
306 313
307 UUID uuid = UUID.Zero; 314 List<string> idList = new List<string>(_kvp.Value.Split(new char[] {','}));
308 UUID.TryParse(_kvp.Value, out uuid);
309 315
310 appearance.SetAttachment(point, uuid, UUID.Zero); 316 appearance.SetAttachment(point, UUID.Zero, UUID.Zero);
317 foreach (string id in idList)
318 {
319 UUID uuid = UUID.Zero;
320 UUID.TryParse(id, out uuid);
321
322 appearance.SetAttachment(point | 0x80, uuid, UUID.Zero);
323 }
311 } 324 }
312 325
313 if (appearance.Wearables[AvatarWearable.BODY].Count == 0) 326 if (appearance.Wearables[AvatarWearable.BODY].Count == 0)