aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
diff options
context:
space:
mode:
authorMelanie Thielker2014-06-21 00:39:55 +0200
committerMelanie Thielker2014-06-21 00:39:55 +0200
commit159fcbf150b7da0e229b29aa7b94793484543d12 (patch)
treeb8c0ff3b4c758a3fba8315b556c923ef4c02a185 /OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
parentMerge commit '68c8633ba18f0a11cfc0ed04d1d0c7c59e6cec76' (diff)
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.zip
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.gz
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.bz2
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.xz
Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
Conflicts: OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs129
1 files changed, 109 insertions, 20 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 6495f3f..d47ca4b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.IO; 31using System.IO;
32using System.Threading;
32using System.Xml; 33using System.Xml;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
@@ -51,6 +52,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 53
53 public int DebugLevel { get; set; } 54 public int DebugLevel { get; set; }
55
56 /// <summary>
57 /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes
58 /// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously.
59 /// </summary>
60 /// <remarks>
61 /// A value of 0 will apply no pause. The pause is specified in milliseconds.
62 /// </remarks>
63 public int ThrottlePer100PrimsRezzed { get; set; }
54 64
55 private Scene m_scene; 65 private Scene m_scene;
56 private IInventoryAccessModule m_invAccessModule; 66 private IInventoryAccessModule m_invAccessModule;
@@ -67,18 +77,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
67 { 77 {
68 IConfig config = source.Configs["Attachments"]; 78 IConfig config = source.Configs["Attachments"];
69 if (config != null) 79 if (config != null)
80 {
70 Enabled = config.GetBoolean("Enabled", true); 81 Enabled = config.GetBoolean("Enabled", true);
82
83 ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0);
84 }
71 else 85 else
86 {
72 Enabled = true; 87 Enabled = true;
88 }
73 } 89 }
74 90
75 public void AddRegion(Scene scene) 91 public void AddRegion(Scene scene)
76 { 92 {
77 m_scene = scene; 93 m_scene = scene;
78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
79
80 if (Enabled) 94 if (Enabled)
81 { 95 {
96 // Only register module with scene if it is enabled. All callers check for a null attachments module.
97 // Ideally, there should be a null attachments module for when this core attachments module has been
98 // disabled. Registering only when enabled allows for other attachments module implementations.
99 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 100 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); 101 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); 102 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
@@ -86,24 +104,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
86 MainConsole.Instance.Commands.AddCommand( 104 MainConsole.Instance.Commands.AddCommand(
87 "Debug", 105 "Debug",
88 false, 106 false,
89 "debug attachments", 107 "debug attachments log",
90 "debug attachments [0|1]", 108 "debug attachments log [0|1]",
91 "Turn on attachments debugging\n" 109 "Turn on attachments debug logging",
92 + " <= 0 - turns off debugging\n" 110 " <= 0 - turns off debug logging\n"
93 + " >= 1 - turns on attachment message logging\n", 111 + " >= 1 - turns on attachment message debug logging",
94 HandleDebugAttachments); 112 HandleDebugAttachmentsLog);
113
114 MainConsole.Instance.Commands.AddCommand(
115 "Debug",
116 false,
117 "debug attachments throttle",
118 "debug attachments throttle <ms>",
119 "Turn on attachments throttling.",
120 "This requires a millisecond value. " +
121 " == 0 - disable throttling.\n"
122 + " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.",
123 HandleDebugAttachmentsThrottle);
124
125 MainConsole.Instance.Commands.AddCommand(
126 "Debug",
127 false,
128 "debug attachments status",
129 "debug attachments status",
130 "Show current attachments debug status",
131 HandleDebugAttachmentsStatus);
95 } 132 }
96 133
97 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 134 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
98 } 135 }
99 136
100 private void HandleDebugAttachments(string module, string[] args) 137 private void HandleDebugAttachmentsLog(string module, string[] args)
101 { 138 {
102 int debugLevel; 139 int debugLevel;
103 140
104 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) 141 if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel)))
105 { 142 {
106 MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); 143 MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]");
107 } 144 }
108 else 145 else
109 { 146 {
@@ -113,6 +150,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
113 } 150 }
114 } 151 }
115 152
153 private void HandleDebugAttachmentsThrottle(string module, string[] args)
154 {
155 int ms;
156
157 if (args.Length == 4 && int.TryParse(args[3], out ms))
158 {
159 ThrottlePer100PrimsRezzed = ms;
160 MainConsole.Instance.OutputFormat(
161 "Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name);
162
163 return;
164 }
165
166 MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>");
167 }
168
169 private void HandleDebugAttachmentsStatus(string module, string[] args)
170 {
171 MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name);
172 MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel);
173 MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed);
174 }
175
116 /// <summary> 176 /// <summary>
117 /// Listen for client triggered running state changes so that we can persist the script's object if necessary. 177 /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
118 /// </summary> 178 /// </summary>
@@ -273,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
273 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 333 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
274 foreach (AvatarAttachment attach in attachments) 334 foreach (AvatarAttachment attach in attachments)
275 { 335 {
276 uint p = (uint)attach.AttachPoint; 336 uint attachmentPt = (uint)attach.AttachPoint;
277 337
278// m_log.DebugFormat( 338// m_log.DebugFormat(
279// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", 339// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}",
@@ -302,13 +362,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
302 // If we're an NPC then skip all the item checks and manipulations since we don't have an 362 // If we're an NPC then skip all the item checks and manipulations since we don't have an
303 // inventory right now. 363 // inventory right now.
304 RezSingleAttachmentFromInventoryInternal( 364 RezSingleAttachmentFromInventoryInternal(
305 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, d); 365 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
306 } 366 }
307 catch (Exception e) 367 catch (Exception e)
308 { 368 {
309 UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; 369 UUID agentId = (sp.ControllingClient == null) ? default(UUID) : sp.ControllingClient.AgentId;
310 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", 370 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}",
311 attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); 371 attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace);
312 } 372 }
313 } 373 }
314 } 374 }
@@ -422,13 +482,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
422 attachPos = Vector3.Zero; 482 attachPos = Vector3.Zero;
423 } 483 }
424 484
425 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment. 485 // if the attachment point is the same as previous, make sure we get the saved
486 // position info.
487 if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint)
488 {
489 attachPos = group.RootPart.AttachedPos;
490 }
491
492 // AttachmentPt 0 means the client chose to 'wear' the attachment.
426 if (attachmentPt == (uint)AttachmentPoint.Default) 493 if (attachmentPt == (uint)AttachmentPoint.Default)
427 { 494 {
428 // Check object for stored attachment point 495 // Check object for stored attachment point
429 attachmentPt = group.AttachmentPoint; 496 attachmentPt = group.AttachmentPoint;
430 } 497 }
431 498
499 // if we didn't find an attach point, look for where it was last attached
500 if (attachmentPt == 0)
501 {
502 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
503 attachPos = group.RootPart.AttachedPos;
504 group.HasGroupChanged = true;
505 }
506
432 // if we still didn't find a suitable attachment point....... 507 // if we still didn't find a suitable attachment point.......
433 if (attachmentPt == 0) 508 if (attachmentPt == 0)
434 { 509 {
@@ -610,6 +685,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
610 if (changed && m_scene.AvatarFactory != null) 685 if (changed && m_scene.AvatarFactory != null)
611 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 686 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
612 687
688 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
689
613 sp.RemoveAttachment(so); 690 sp.RemoveAttachment(so);
614 so.FromItemID = UUID.Zero; 691 so.FromItemID = UUID.Zero;
615 692
@@ -841,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
841 m_scene.ForEachClient( 918 m_scene.ForEachClient(
842 client => 919 client =>
843 { if (client.AgentId != so.AttachedAvatar) 920 { if (client.AgentId != so.AttachedAvatar)
844 client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId }); 921 client.SendKillObject(new List<uint>() { so.LocalId });
845 }); 922 });
846 } 923 }
847 924
@@ -982,8 +1059,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
982 1059
983 if (DebugLevel > 0) 1060 if (DebugLevel > 0)
984 m_log.DebugFormat( 1061 m_log.DebugFormat(
985 "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", 1062 "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}",
986 objatt.Name, sp.Name, attachmentPt, m_scene.Name); 1063 objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
987 1064
988 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 1065 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
989 objatt.HasGroupChanged = false; 1066 objatt.HasGroupChanged = false;
@@ -1020,7 +1097,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1020 } 1097 }
1021 1098
1022 if (tainted) 1099 if (tainted)
1023 objatt.HasGroupChanged = true; 1100 objatt.HasGroupChanged = true;
1101
1102 if (ThrottlePer100PrimsRezzed > 0)
1103 {
1104 int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed);
1105
1106 if (DebugLevel > 0)
1107 m_log.DebugFormat(
1108 "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}",
1109 throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
1110
1111 Thread.Sleep(throttleMs);
1112 }
1024 1113
1025 return objatt; 1114 return objatt;
1026 } 1115 }