diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 3203fc1d7d..d5ae3b7ebd 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1273,7 +1273,7 @@ namespace OpenSim.Framework /// /// Created to work around a limitation in Mono with nested delegates /// - private class FireAndForgetWrapper + /*private class FireAndForgetWrapper { public void FireAndForget(System.Threading.WaitCallback callback) { @@ -1284,21 +1284,23 @@ namespace OpenSim.Framework { callback.BeginInvoke(obj, EndFireAndForget, callback); } - } + }*/ public static void FireAndForget(System.Threading.WaitCallback callback) { - FireAndForgetWrapper wrapper = Singleton.GetInstance(); - wrapper.FireAndForget(callback); + //FireAndForgetWrapper wrapper = Singleton.GetInstance(); + //wrapper.FireAndForget(callback); + System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, null); } public static void FireAndForget(System.Threading.WaitCallback callback, object obj) { - FireAndForgetWrapper wrapper = Singleton.GetInstance(); - wrapper.FireAndForget(callback, obj); + //FireAndForgetWrapper wrapper = Singleton.GetInstance(); + //wrapper.FireAndForget(callback, obj); + System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj); } - private static void EndFireAndForget(IAsyncResult ar) + /*private static void EndFireAndForget(IAsyncResult ar) { System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; @@ -1306,7 +1308,7 @@ namespace OpenSim.Framework catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } ar.AsyncWaitHandle.Close(); - } + }*/ #endregion FireAndForget Threading Pattern } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 1c463ea9ac..b0278825b2 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -321,12 +321,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP private readonly IGroupsModule m_GroupsModule; private int m_cachedTextureSerial; - private PriorityQueue m_avatarTerseUpdates = - new PriorityQueue(); - private PriorityQueue m_primTerseUpdates = - new PriorityQueue(); - private PriorityQueue m_primFullUpdates = - new PriorityQueue(); + private PriorityQueue m_avatarTerseUpdates; + private PriorityQueue m_primTerseUpdates; + private PriorityQueue m_primFullUpdates; private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; @@ -335,7 +332,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers - protected IScene m_scene; + protected Scene m_scene; protected LLImageManager m_imageManager; protected string m_firstName; protected string m_lastName; @@ -408,16 +405,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Constructor /// - public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, + public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode) { RegisterInterface(this); RegisterInterface(this); RegisterInterface(this); - + InitDefaultAnimations(); m_scene = scene; + + m_avatarTerseUpdates = new PriorityQueue(); + m_primTerseUpdates = new PriorityQueue(); + m_primFullUpdates = new PriorityQueue(m_scene.Entities.Count); + m_assetService = m_scene.RequestModuleInterface(); m_hyperAssets = m_scene.RequestModuleInterface(); m_GroupsModule = scene.RequestModuleInterface(); @@ -3288,10 +3290,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } Quaternion rotation = data.Rotation; - - if (rotation.X == rotation.Y && - rotation.Y == rotation.Z && - rotation.Z == rotation.W && rotation.W == 0.0f) + if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f) rotation = Quaternion.Identity; ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data); @@ -3377,15 +3376,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } Quaternion rotation = data.rotation; + if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f) + rotation = Quaternion.Identity; if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD return; - if (data.primShape.PCode == 9 && data.primShape.State != 0 && data.parentID == 0) + if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9) return; - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0.0f) - rotation = Quaternion.Identity; - ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data); lock (m_primFullUpdates.SyncRoot) @@ -3397,7 +3395,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); outPacket.Header.Zerocoded = true; - //outPacket.RegionData = new ObjectUpdatePacket.RegionDataBlock(); outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); @@ -3424,13 +3421,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } Quaternion rotation = data.Rotation; + if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f) + rotation = Quaternion.Identity; if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD return; - if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) - rotation = Quaternion.Identity; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data); lock (m_primTerseUpdates.SyncRoot) @@ -10238,10 +10234,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id); - private MinHeap[] heaps = new MinHeap[1]; - private Dictionary lookup_table = new Dictionary(); - private Comparison comparison; - private object sync_root = new object(); + private MinHeap[] m_heaps = new MinHeap[1]; + private Dictionary m_lookupTable; + private Comparison m_comparison; + private object m_syncRoot = new object(); internal PriorityQueue() : this(MinHeap.DEFAULT_CAPACITY, Comparer.Default) { } @@ -10255,19 +10251,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP this(capacity, new Comparison(comparer.Compare)) { } internal PriorityQueue(int capacity, Comparison comparison) { - for (int i = 0; i < heaps.Length; ++i) - heaps[i] = new MinHeap(capacity); - this.comparison = comparison; + m_lookupTable = new Dictionary(capacity); + + for (int i = 0; i < m_heaps.Length; ++i) + m_heaps[i] = new MinHeap(capacity); + this.m_comparison = comparison; } - internal object SyncRoot { get { return this.sync_root; } } + internal object SyncRoot { get { return this.m_syncRoot; } } internal int Count { get { int count = 0; - for (int i = 0; i < heaps.Length; ++i) - count = heaps[i].Count; + for (int i = 0; i < m_heaps.Length; ++i) + count = m_heaps[i].Count; return count; } } @@ -10276,36 +10274,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP { LookupItem item; - if (lookup_table.TryGetValue(local_id, out item)) + if (m_lookupTable.TryGetValue(local_id, out item)) { - item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.comparison); + item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison); return false; } else { - item.Heap = heaps[0]; - item.Heap.Add(new MinHeapItem(priority, value, local_id, this.comparison), ref item.Handle); - lookup_table.Add(local_id, item); + item.Heap = m_heaps[0]; + item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle); + m_lookupTable.Add(local_id, item); return true; } } internal TValue Peek() { - for (int i = 0; i < heaps.Length; ++i) - if (heaps[i].Count > 0) - return heaps[i].Min().Value; + for (int i = 0; i < m_heaps.Length; ++i) + if (m_heaps[i].Count > 0) + return m_heaps[i].Min().Value; throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); } internal TValue Dequeue() { - for (int i = 0; i < heaps.Length; ++i) + for (int i = 0; i < m_heaps.Length; ++i) { - if (heaps[i].Count > 0) + if (m_heaps[i].Count > 0) { - MinHeapItem item = heaps[i].RemoveMin(); - lookup_table.Remove(item.LocalID); + MinHeapItem item = m_heaps[i].RemoveMin(); + m_lookupTable.Remove(item.LocalID); return item.Value; } } @@ -10317,7 +10315,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP MinHeapItem item; TPriority priority; - foreach (LookupItem lookup in new List(this.lookup_table.Values)) + foreach (LookupItem lookup in new List(this.m_lookupTable.Values)) { if (lookup.Heap.TryGetValue(lookup.Handle, out item)) { @@ -10332,7 +10330,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update"); lookup.Heap.Remove(lookup.Handle); - this.lookup_table.Remove(item.LocalID); + this.m_lookupTable.Remove(item.LocalID); } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs index d25bf95ec0..938cf50468 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs @@ -51,7 +51,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private bool m_shuttingdown; - private long m_lastloopprocessed; private AssetBase m_missingImage; private LLClientView m_client; //Client we're assigned to private IAssetService m_assetCache; //Asset Cache @@ -169,7 +168,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP public bool ProcessImageQueue(int packetsToSend) { - m_lastloopprocessed = DateTime.Now.Ticks; int packetsSent = 0; while (packetsSent < packetsToSend) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 9476eed5dc..4b6a358588 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -506,8 +506,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// for private void BeginFireQueueEmpty(int throttleIndex) { - if (!m_onQueueEmptyRunning[throttleIndex]) - Util.FireAndForget(FireQueueEmpty, throttleIndex); + // Unknown is -1 and Resend is 0. Make sure we are only firing the + // callback for categories other than those + if (throttleIndex > 0) + { + if (!m_onQueueEmptyRunning[throttleIndex]) + Util.FireAndForget(FireQueueEmpty, throttleIndex); + } } /// diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 66e1468a91..74175d0cee 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -107,7 +107,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Manages authentication for agent circuits private AgentCircuitManager m_circuitManager; /// Reference to the scene this UDP server is attached to - private IScene m_scene; + private Scene m_scene; /// The X/Y coordinates of the scene this UDP server is attached to private Location m_location; /// The measured resolution of Environment.TickCount @@ -184,15 +184,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void AddScene(IScene scene) { - if (m_scene == null) - { - m_scene = scene; - m_location = new Location(m_scene.RegionInfo.RegionHandle); - } - else + if (m_scene != null) { m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); + return; } + + if (!(scene is Scene)) + { + m_log.Error("[LLUDPSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType()); + return; + } + + m_scene = (Scene)scene; + m_location = new Location(m_scene.RegionInfo.RegionHandle); } public bool HandlesRegion(Location x) @@ -794,7 +799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP elapsed500MS = 0; } - m_scene.ClientManager.ForEach( + m_scene.ClientManager.ForEachSync( delegate(IClientAPI client) { if (client is LLClientView) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 332d3ce59e..53c64cb57d 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -147,9 +147,10 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelDwellRequest += ClientOnParcelDwellRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; - if (m_scene.Entities.ContainsKey(client.AgentId)) + EntityBase presenceEntity; + if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) { - SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true); + SendLandUpdate((ScenePresence)presenceEntity, true); SendParcelOverlay(client); } } diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index b9b7da5bc0..bfe85f1e04 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -139,10 +139,8 @@ namespace OpenSim.Region.CoreModules.World.Land } else { - //Normal Calculations - return Convert.ToInt32( - Math.Round((Convert.ToDecimal(LandData.Area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity * - Convert.ToDecimal(m_scene.RegionInfo.RegionSettings.ObjectBonus))); ; + // Normal Calculations + return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.objectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); } } public int GetSimulatorMaxPrimCount(ILandObject thisObject) diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs index 0ceef3911a..099fcce559 100644 --- a/OpenSim/Region/Framework/Scenes/EntityManager.cs +++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs @@ -93,40 +93,31 @@ namespace OpenSim.Region.Framework.Scenes { get { - lock (m_lock) - { - return m_eb_uuid.Count; - } + return m_eb_uuid.Count; } } public bool ContainsKey(UUID id) { - lock (m_lock) + try { - try - { - return m_eb_uuid.ContainsKey(id); - } - catch - { - return false; - } + return m_eb_uuid.ContainsKey(id); + } + catch + { + return false; } } public bool ContainsKey(uint localID) { - lock (m_lock) + try { - try - { - return m_eb_localID.ContainsKey(localID); - } - catch - { - return false; - } + return m_eb_localID.ContainsKey(localID); + } + catch + { + return false; } } @@ -136,7 +127,11 @@ namespace OpenSim.Region.Framework.Scenes { try { - bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID); + bool a = false; + EntityBase entity; + if (m_eb_localID.TryGetValue(localID, out entity)) + a = m_eb_uuid.Remove(entity.UUID); + bool b = m_eb_localID.Remove(localID); return a && b; } @@ -154,7 +149,11 @@ namespace OpenSim.Region.Framework.Scenes { try { - bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId); + bool a = false; + EntityBase entity; + if (m_eb_uuid.TryGetValue(id, out entity)) + a = m_eb_localID.Remove(entity.LocalId); + bool b = m_eb_uuid.Remove(id); return a && b; } @@ -206,14 +205,11 @@ namespace OpenSim.Region.Framework.Scenes { lock (m_lock) { - try - { - return m_eb_uuid[id]; - } - catch - { + EntityBase entity; + if (m_eb_uuid.TryGetValue(id, out entity)) + return entity; + else return null; - } } } set @@ -228,14 +224,11 @@ namespace OpenSim.Region.Framework.Scenes { lock (m_lock) { - try - { - return m_eb_localID[localID]; - } - catch - { + EntityBase entity; + if (m_eb_localID.TryGetValue(localID, out entity)) + return entity; + else return null; - } } } set diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index c44c4c7940..c2b9e7371c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2351,12 +2351,6 @@ namespace OpenSim.Region.Framework.Scenes item = InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); - IAvatarFactory ava = RequestModuleInterface(); - if (ava != null) - { - ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - } return att.UUID; } @@ -2402,12 +2396,6 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); - - if (m_AvatarFactory != null) - { - m_log.InfoFormat("[SCENE INVENTORY]: Saving avatar attachment. AgentID:{0} ItemID:{1} AttachmentPoint:{2}", remoteClient.AgentId, itemID, AttachmentPt); - m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } } } @@ -2447,12 +2435,13 @@ namespace OpenSim.Region.Framework.Scenes if (TryGetAvatar(remoteClient.AgentId, out presence)) { presence.Appearance.DetachAttachment(itemID); - IAvatarFactory ava = RequestModuleInterface(); - if (ava != null) - { - ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } + // Save avatar attachment information + if (m_AvatarFactory != null) + { + m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", ItemID: " + itemID); + m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } } m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 70b11c328e..4f3cc9838c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -228,6 +228,10 @@ namespace OpenSim.Region.Framework.Scenes protected IXMLRPC m_xmlrpcModule; protected IWorldComm m_worldCommModule; protected IAvatarFactory m_AvatarFactory; + public IAvatarFactory AvatarFactory + { + get { return m_AvatarFactory; } + } protected IConfigSource m_config; protected IRegionSerialiserModule m_serialiser; protected IInterregionCommsOut m_interregionCommsOut; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 8ee26c3cd7..e51f6ef9bd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -467,7 +467,6 @@ namespace OpenSim.Region.Framework.Scenes protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) { // If we can't take it, we can't attach it! - // SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID); if (part == null) return; @@ -477,9 +476,16 @@ namespace OpenSim.Region.Framework.Scenes return; // Calls attach with a Zero position - // AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false); m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); + + // Save avatar attachment information + ScenePresence presence; + if (m_parentScene.AvatarFactory != null && m_parentScene.TryGetAvatar(remoteClient.AgentId, out presence)) + { + m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", AttachmentPoint: " + AttachmentPt); + m_parentScene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } } public SceneObjectGroup RezSingleAttachment( @@ -574,7 +580,7 @@ namespace OpenSim.Region.Framework.Scenes } - group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); + group.SetAttachmentPoint((byte)AttachmentPt); group.AbsolutePosition = attachPos; // Saves and gets itemID diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 2153b9b8cb..810dfd1d83 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -899,7 +899,7 @@ namespace OpenSim.Region.Framework.Scenes SetAttachmentPoint(Convert.ToByte(attachmentpoint)); avatar.AddAttachment(this); - m_log.DebugFormat("[SOG]: Added att {0} to avie {1}", UUID, avatar.UUID); + m_log.Debug("[SOG]: Added attachment " + UUID + " to avatar " + avatar.UUID); if (!silent) {