From 142008121e2e9c5ca5fca5de07b8a14e37279800 Mon Sep 17 00:00:00 2001
From: John Hurliman
Date: Mon, 19 Oct 2009 15:19:09 -0700
Subject: * Change Util.FireAndForget to use
ThreadPool.UnsafeQueueUserWorkItem(). This avoids .NET remoting and a
managed->unmanaged->managed jump. Overall, a night and day performance
difference * Initialize the LLClientView prim full update queue to the number
of prims in the scene for a big performance boost * Reordered some
comparisons on hot code paths for a minor speed boost * Removed an
unnecessary call to the expensive DateTime.Now function (if you *have* to get
the current time as opposed to Environment.TickCount, always use
DateTime.UtcNow) * Don't fire the queue empty callback for the Resend
category * Run the outgoing packet handler thread loop for each client
synchronously. It seems like more time was being spent doing the execution
asynchronously, and it made deadlocks very difficult to track down * Rewrote
some expensive math in LandObject.cs * Optimized EntityManager to only lock
on operations that need locking, and use TryGetValue() where possible * Only
update the attachment database when an object is attached or detached * Other
small misc. performance improvements
---
OpenSim/Framework/Util.cs | 18 +++--
.../Region/ClientStack/LindenUDP/LLClientView.cs | 88 +++++++++++-----------
.../Region/ClientStack/LindenUDP/LLImageManager.cs | 2 -
.../Region/ClientStack/LindenUDP/LLUDPClient.cs | 9 ++-
.../Region/ClientStack/LindenUDP/LLUDPServer.cs | 19 +++--
.../CoreModules/World/Land/LandManagementModule.cs | 5 +-
.../Region/CoreModules/World/Land/LandObject.cs | 6 +-
OpenSim/Region/Framework/Scenes/EntityManager.cs | 69 ++++++++---------
OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 21 ++----
OpenSim/Region/Framework/Scenes/Scene.cs | 4 +
OpenSim/Region/Framework/Scenes/SceneGraph.cs | 12 ++-
.../Region/Framework/Scenes/SceneObjectGroup.cs | 2 +-
12 files changed, 127 insertions(+), 128 deletions(-)
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 3203fc1..d5ae3b7 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 1c463ea..b027882 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 d25bf95..938cf50 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 9476eed..4b6a358 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 66e1468..74175d0 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)
+ if (m_scene != null)
{
- m_scene = scene;
- m_location = new Location(m_scene.RegionInfo.RegionHandle);
+ m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
+ return;
}
- else
+
+ if (!(scene is Scene))
{
- m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a 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 332d3ce..53c64cb 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 b9b7da5..bfe85f1 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 0ceef39..099fcce 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 c44c4c7..c2b9e73 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)
+
+ // Save avatar attachment information
+ if (m_AvatarFactory != null)
{
- ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
+ 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 70b11c3..4f3cc98 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 8ee26c3..e51f6ef 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 2153b9b..810dfd1 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)
{
--
cgit v1.1