From ff0ccf9c67e3840c39729e1ce9677b96e0cfd472 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Aug 2016 14:30:27 +0100 Subject: [PATCH 01/41] several changes related to culling option --- OpenSim/Framework/IClientAPI.cs | 52 ++--- OpenSim/Framework/PriorityQueue.cs | 12 +- .../ClientStack/Linden/UDP/LLClientView.cs | 190 +++++++++--------- 3 files changed, 117 insertions(+), 137 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 018f19435b..0140733064 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -585,10 +585,10 @@ namespace OpenSim.Framework public float dwell; } - public class IEntityUpdate + public class EntityUpdate { private ISceneEntity m_entity; - private uint m_flags; + private PrimUpdateFlags m_flags; private int m_updateTime; public ISceneEntity Entity @@ -596,7 +596,7 @@ namespace OpenSim.Framework get { return m_entity; } } - public uint Flags + public PrimUpdateFlags Flags { get { return m_flags; } } @@ -606,23 +606,31 @@ namespace OpenSim.Framework get { return m_updateTime; } } - public virtual void Update(IEntityUpdate update) + public virtual void Update(EntityUpdate update) { - m_flags |= update.Flags; + PrimUpdateFlags updateFlags = update.Flags; + if(updateFlags.HasFlag(PrimUpdateFlags.CancelKill)) + m_flags = PrimUpdateFlags.FullUpdate; + else if(m_flags.HasFlag(PrimUpdateFlags.Kill)) + return; + else if(updateFlags.HasFlag(PrimUpdateFlags.Kill)) + m_flags = PrimUpdateFlags.Kill; + else + m_flags |= updateFlags; // Use the older of the updates as the updateTime if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0) m_updateTime = update.UpdateTime; } - public IEntityUpdate(ISceneEntity entity, uint flags) + public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags) { m_entity = entity; m_flags = flags; m_updateTime = Util.EnvironmentTickCount(); } - public IEntityUpdate(ISceneEntity entity, uint flags, Int32 updateTime) + public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, Int32 updateTime) { m_entity = entity; m_flags = flags; @@ -630,29 +638,6 @@ namespace OpenSim.Framework } } - public class EntityUpdate : IEntityUpdate - { - private float m_timeDilation; - - public float TimeDilation - { - get { return m_timeDilation; } - } - - public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation) - : base(entity, (uint)flags) - { - // Flags = flags; - m_timeDilation = timedilation; - } - - public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, float timedilation, Int32 updateTime) - : base(entity,(uint)flags,updateTime) - { - m_timeDilation = timedilation; - } - } - public class PlacesReplyData { public UUID OwnerID; @@ -701,9 +686,12 @@ namespace OpenSim.Framework ExtraData = 1 << 20, Sound = 1 << 21, Joint = 1 << 22, - FullUpdate = UInt32.MaxValue + FullUpdate = 0x3fffffff, + CancelKill = 0x7fffffff, + Kill = 0x80000000 } +/* included in .net 4.0 public static class PrimUpdateFlagsExtensions { public static bool HasFlag(this PrimUpdateFlags updateFlags, PrimUpdateFlags flag) @@ -711,7 +699,7 @@ namespace OpenSim.Framework return (updateFlags & flag) == flag; } } - +*/ public interface IClientAPI { Vector3 StartPos { get; set; } diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs index 4f05f6540a..fec01da4bf 100644 --- a/OpenSim/Framework/PriorityQueue.cs +++ b/OpenSim/Framework/PriorityQueue.cs @@ -113,7 +113,7 @@ namespace OpenSim.Framework /// /// Enqueue an item into the specified priority queue /// - public bool Enqueue(uint pqueue, IEntityUpdate value) + public bool Enqueue(uint pqueue, EntityUpdate value) { LookupItem lookup; @@ -154,7 +154,7 @@ namespace OpenSim.Framework /// oldest item from the next queue in order to provide fair access to /// all of the queues /// - public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) + public bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue) { // If there is anything in imediate queues, return it first no // matter what else. Breaks fairness. But very useful. @@ -212,7 +212,7 @@ namespace OpenSim.Framework } timeinqueue = 0; - value = default(IEntityUpdate); + value = default(EntityUpdate); return false; } @@ -270,8 +270,8 @@ namespace OpenSim.Framework #region MinHeapItem private struct MinHeapItem : IComparable { - private IEntityUpdate value; - internal IEntityUpdate Value { + private EntityUpdate value; + internal EntityUpdate Value { get { return this.value; } @@ -307,7 +307,7 @@ namespace OpenSim.Framework this.pqueue = pqueue; } - internal MinHeapItem(uint pqueue, UInt64 entryorder, IEntityUpdate value) + internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value) { this.entrytime = Util.EnvironmentTickCount(); this.entryorder = entryorder; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index e3b2fd1f85..b823abe592 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3937,7 +3937,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP uint priority = m_prioritizer.GetUpdatePriority(this, entity); lock (m_entityUpdates.SyncRoot) - m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); + m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags)); } /// @@ -4006,12 +4006,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race // condition where a kill can be processed before an out-of-date update for the same object. // float avgTimeDilation = 0.0f; - IEntityUpdate iupdate; + EntityUpdate update; Int32 timeinqueue; // this is just debugging code & can be dropped later bool doCulling = m_scene.ObjectsCullingByDistance; float cullingrange = 64.0f; HashSet GroupsNeedFullUpdate = new HashSet(); + List kills = new List(); // Vector3 mycamera = Vector3.Zero; Vector3 mypos = Vector3.Zero; ScenePresence mysp = (ScenePresence)SceneAgent; @@ -4027,12 +4028,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP while (updatesThisCall < maxUpdates) { lock (m_entityUpdates.SyncRoot) - if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue)) + if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) break; - - EntityUpdate update = (EntityUpdate)iupdate; - + // avgTimeDilation += update.TimeDilation; + PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; + + if(updateFlags.HasFlag(PrimUpdateFlags.Kill)) + { + m_killRecord.Add(update.Entity.LocalId); + continue; + } if (update.Entity is SceneObjectPart) { @@ -4156,11 +4162,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region UpdateFlags to packet type conversion - PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; - bool canUseCompressed = true; bool canUseImproved = true; + // Compressed object updates only make sense for LL primitives if (!(update.Entity is SceneObjectPart)) { @@ -4319,17 +4324,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_killRecord.Clear(); } + if (kills.Count > 0) + { + foreach(SceneObjectGroup grp in kills) + { + foreach(SceneObjectPart p in grp.Parts) + SendEntityUpdate(p,PrimUpdateFlags.Kill); + } + kills.Clear(); + } + if(GroupsNeedFullUpdate.Count > 0) { foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) { - grp.ScheduleGroupForFullUpdate(); + foreach(SceneObjectPart p in grp.Parts) + SendEntityUpdate(p,PrimUpdateFlags.CancelKill); lock(GroupsInView) GroupsInView.Add(grp); } } #endregion - } // hack.. dont use @@ -4368,7 +4383,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } private bool CheckGroupsInViewBusy = false; - private bool CheckGroupsInViewOverRun = false; public void CheckGroupsInView() { @@ -4377,112 +4391,90 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; if(CheckGroupsInViewBusy) + return; + + CheckGroupsInViewBusy = true; + + float cullingrange = 64.0f; +// Vector3 mycamera = Vector3.Zero; + Vector3 mypos = Vector3.Zero; + ScenePresence mysp = (ScenePresence)SceneAgent; + if(mysp != null && !mysp.IsDeleted) { - CheckGroupsInViewOverRun = true; + cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; +// mycamera = mysp.CameraPosition; + mypos = mysp.AbsolutePosition; + } + else + { + CheckGroupsInViewBusy= false; return; } - CheckGroupsInViewBusy = true; - do + + HashSet NewGroupsInView = new HashSet(); + HashSet GroupsNeedFullUpdate = new HashSet(); + List kills = new List(); + + EntityBase[] entities = m_scene.Entities.GetEntities(); + foreach (EntityBase e in entities) { - CheckGroupsInViewOverRun = false; - - float cullingrange = 64.0f; -// Vector3 mycamera = Vector3.Zero; - Vector3 mypos = Vector3.Zero; - ScenePresence mysp = (ScenePresence)SceneAgent; - if(mysp != null && !mysp.IsDeleted) - { - cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; -// mycamera = mysp.CameraPosition; - mypos = mysp.AbsolutePosition; - } - else - { - CheckGroupsInViewBusy= false; + if(!IsActive) return; - } - HashSet NewGroupsInView = new HashSet(); - HashSet GroupsNeedFullUpdate = new HashSet(); - List kills = new List(); - int killedParst = 0; - - EntityBase[] entities = m_scene.Entities.GetEntities(); - foreach (EntityBase e in entities) + if (e != null && e is SceneObjectGroup) { - if(!IsActive) - return; + SceneObjectGroup grp = (SceneObjectGroup)e; + if(grp.IsDeleted || grp.IsAttachment) + continue; - if (e != null && e is SceneObjectGroup) - { - SceneObjectGroup grp = (SceneObjectGroup)e; - if(grp.IsDeleted || grp.IsAttachment) - continue; - - float bradius = grp.GetBoundsRadius(); - Vector3 grppos = grp.AbsolutePosition + grp.getBoundsCenter(); + float bradius = grp.GetBoundsRadius(); + Vector3 grppos = grp.AbsolutePosition + grp.getBoundsCenter(); // float dcam = (grppos - mycamera).LengthSquared(); - float dpos = (grppos - mypos).LengthSquared(); + float dpos = (grppos - mypos).LengthSquared(); // if(dcam < dpos) // dpos = dcam; - dpos = (float)Math.Sqrt(dpos) - bradius; + dpos = (float)Math.Sqrt(dpos) - bradius; - bool inview; - lock(GroupsInView) - inview = GroupsInView.Contains(grp); + bool inview; + lock(GroupsInView) + inview = GroupsInView.Contains(grp); - if(dpos > cullingrange) - { - if(inview) - { - kills.Add(grp.LocalId); - killedParst += grp.PrimCount; - - if (killedParst > 199 ) - { - SendKillObject(kills); - kills.Clear(); - killedParst = 0; - Thread.Sleep(50); - if(mysp != null && !mysp.IsDeleted) - { - cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; -// mycamera = mysp.CameraPosition; - mypos = mysp.AbsolutePosition; - } - else - { - CheckGroupsInViewBusy= false; - return; - } - } - } - } - else - { - if(!inview) - GroupsNeedFullUpdate.Add(grp); - NewGroupsInView.Add(grp); - } + if(dpos > cullingrange) + { + if(inview) + kills.Add(grp); + } + else + { + if(!inview) + GroupsNeedFullUpdate.Add(grp); + NewGroupsInView.Add(grp); } } + } - lock(GroupsInView) - GroupsInView = NewGroupsInView; + lock(GroupsInView) + GroupsInView = NewGroupsInView; - if (kills.Count > 0) + if (kills.Count > 0) + { + foreach(SceneObjectGroup grp in kills) { - SendKillObject(kills); - kills.Clear(); + foreach(SceneObjectPart p in grp.Parts) + SendEntityUpdate(p,PrimUpdateFlags.Kill); } + kills.Clear(); + } - if(GroupsNeedFullUpdate.Count > 0) + if(GroupsNeedFullUpdate.Count > 0) + { + foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) { - foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) - grp.ScheduleGroupForFullUpdate(); + foreach(SceneObjectPart p in grp.Parts) + SendEntityUpdate(p,PrimUpdateFlags.CancelKill); } - } while(CheckGroupsInViewOverRun); + } CheckGroupsInViewBusy = false; } @@ -4670,13 +4662,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(pack, ThrottleOutPacketType.Task); } - private class ObjectPropertyUpdate : IEntityUpdate + private class ObjectPropertyUpdate : EntityUpdate { internal bool SendFamilyProps; internal bool SendObjectProps; public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj) - : base(entity,flags) + : base(entity,(PrimUpdateFlags)flags) { SendFamilyProps = sendfam; SendObjectProps = sendobj; @@ -4745,7 +4737,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OpenSim.Framework.Lazy> propertyUpdates = new OpenSim.Framework.Lazy>(); - IEntityUpdate iupdate; + EntityUpdate iupdate; Int32 timeinqueue; // this is just debugging code & can be dropped later int updatesThisCall = 0; @@ -4849,11 +4841,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt); } - private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags) + private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, PrimUpdateFlags requestFlags) { ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); - block.RequestFlags = requestFlags; + block.RequestFlags = (uint)requestFlags; block.ObjectID = sop.UUID; if (sop.OwnerID == sop.GroupID) block.OwnerID = UUID.Zero; From c255c23981a3023e3587a71872bbaeb6fcd62093 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Aug 2016 17:07:09 +0100 Subject: [PATCH 02/41] move updates from updates queues into udp queues acording to their payload estimated size and udp sending capability on a time slice, instead always moving a arbitrary number of updates. --- .../ClientStack/Linden/UDP/LLClientView.cs | 81 ++++++++++--------- .../ClientStack/Linden/UDP/LLUDPClient.cs | 5 +- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index b823abe592..6beb9b42a9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3982,7 +3982,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ResendPrimUpdate(update); } - private void ProcessEntityUpdates(int maxUpdates) + private void ProcessEntityUpdates(int maxUpdatesBytes) { OpenSim.Framework.Lazy> objectUpdateBlocks = new OpenSim.Framework.Lazy>(); OpenSim.Framework.Lazy> compressedUpdateBlocks = new OpenSim.Framework.Lazy>(); @@ -3996,16 +3996,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Check to see if this is a flush - if (maxUpdates <= 0) + if (maxUpdatesBytes <= 0) { - maxUpdates = Int32.MaxValue; + maxUpdatesBytes = Int32.MaxValue; } - int updatesThisCall = 0; - - // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race - // condition where a kill can be processed before an out-of-date update for the same object. -// float avgTimeDilation = 0.0f; EntityUpdate update; Int32 timeinqueue; // this is just debugging code & can be dropped later @@ -4018,25 +4013,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP ScenePresence mysp = (ScenePresence)SceneAgent; if(mysp != null && !mysp.IsDeleted) { - cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance +16f; + cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; // mycamera = mysp.CameraPosition; mypos = mysp.AbsolutePosition; } else doCulling = false; - while (updatesThisCall < maxUpdates) + while (maxUpdatesBytes > 0) { lock (m_entityUpdates.SyncRoot) if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) break; -// avgTimeDilation += update.TimeDilation; PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; if(updateFlags.HasFlag(PrimUpdateFlags.Kill)) { m_killRecord.Add(update.Entity.LocalId); + maxUpdatesBytes -= 30; continue; } @@ -4158,8 +4153,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP continue; } - ++updatesThisCall; - #region UpdateFlags to packet type conversion bool canUseCompressed = true; @@ -4212,30 +4205,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP // TODO: Remove this once we can build compressed updates canUseCompressed = false; - + if (!canUseImproved && !canUseCompressed) { if (update.Entity is ScenePresence) { - objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); + ObjectUpdatePacket.ObjectDataBlock ablock = + CreateAvatarUpdateBlock((ScenePresence)update.Entity); + objectUpdateBlocks.Value.Add(ablock); + maxUpdatesBytes -= ablock.Length; } else { - objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); + ObjectUpdatePacket.ObjectDataBlock ablock = + CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId); + objectUpdateBlocks.Value.Add(ablock); + maxUpdatesBytes -= ablock.Length; } } else if (!canUseImproved) { - compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); + ObjectUpdateCompressedPacket.ObjectDataBlock ablock = + CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags); + compressedUpdateBlocks.Value.Add(ablock); + maxUpdatesBytes -= ablock.Length; } else { if (update.Entity is ScenePresence) + { // ALL presence updates go into a special list - terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock ablock = + CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); + terseAgentUpdateBlocks.Value.Add(ablock); + maxUpdatesBytes -= ablock.Length; + } else + { // Everything else goes here - terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock ablock = + CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); + terseUpdateBlocks.Value.Add(ablock); + maxUpdatesBytes -= ablock.Length; + } } #endregion Block Construction @@ -4504,8 +4516,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP // of updates converted to packets. Since we don't want packets // to sit in the queue with old data, only convert enough updates // to packets that can be sent in 200ms. - private Int32 m_LastQueueFill = 0; - private Int32 m_maxUpdates = 0; +// private Int32 m_LastQueueFill = 0; +// private Int32 m_maxUpdates = 0; void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) { @@ -4516,7 +4528,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // if (!m_udpServer.IsRunningOutbound) // return; - +/* if (m_maxUpdates == 0 || m_LastQueueFill == 0) { m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; @@ -4530,17 +4542,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP } m_maxUpdates = Util.Clamp(m_maxUpdates,10,500); m_LastQueueFill = Util.EnvironmentTickCount(); - +*/ + int maxUpdateBytes = m_udpClient.GetCatBytesCanSend(ThrottleOutPacketType.Task, 30); + if (m_entityUpdates.Count > 0) - ProcessEntityUpdates(m_maxUpdates); + ProcessEntityUpdates(maxUpdateBytes); if (m_entityProps.Count > 0) - ProcessEntityPropertyRequests(m_maxUpdates); + ProcessEntityPropertyRequests(maxUpdateBytes); } if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); - } + } internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories) { @@ -4723,7 +4737,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true)); } - private void ProcessEntityPropertyRequests(int maxUpdates) + private void ProcessEntityPropertyRequests(int maxUpdateBytes) { OpenSim.Framework.Lazy> objectFamilyBlocks = new OpenSim.Framework.Lazy>(); @@ -4740,8 +4754,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP EntityUpdate iupdate; Int32 timeinqueue; // this is just debugging code & can be dropped later - int updatesThisCall = 0; - while (updatesThisCall < m_maxUpdates) + while (maxUpdateBytes > 0) { lock (m_entityProps.SyncRoot) if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) @@ -4756,6 +4769,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); objectFamilyBlocks.Value.Add(objPropDB); familyUpdates.Value.Add(update); + maxUpdateBytes -= objPropDB.Length; } } @@ -4767,16 +4781,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); objectPropertiesBlocks.Value.Add(objPropDB); propertyUpdates.Value.Add(update); + maxUpdateBytes -= objPropDB.Length; } } - - updatesThisCall++; } - - - // Int32 ppcnt = 0; - // Int32 pbcnt = 0; - + if (objectPropertiesBlocks.IsValueCreated) { List blocks = objectPropertiesBlocks.Value; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 36e0a0e010..4e68a9b1c8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -771,8 +771,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP RTO = Math.Min(RTO * 2, m_maxRTO); } - - const int MIN_CALLBACK_MS = 10; + const int MIN_CALLBACK_MS = 20; /// /// Does an early check to see if this queue empty callback is already @@ -807,9 +806,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } else - { m_isQueueEmptyRunning = false; - } } } From a30f75cfdc7e22ae108d2e48597c80166680a45d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Aug 2016 20:53:38 +0100 Subject: [PATCH 03/41] fix entity update flags update --- OpenSim/Framework/IClientAPI.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 0140733064..848d574fe3 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -606,21 +606,20 @@ namespace OpenSim.Framework get { return m_updateTime; } } - public virtual void Update(EntityUpdate update) + public virtual void Update(EntityUpdate oldupdate) { - PrimUpdateFlags updateFlags = update.Flags; - if(updateFlags.HasFlag(PrimUpdateFlags.CancelKill)) + // we are on the new one + PrimUpdateFlags updateFlags = oldupdate.Flags; + if(m_flags.HasFlag(PrimUpdateFlags.CancelKill)) m_flags = PrimUpdateFlags.FullUpdate; - else if(m_flags.HasFlag(PrimUpdateFlags.Kill)) - return; else if(updateFlags.HasFlag(PrimUpdateFlags.Kill)) - m_flags = PrimUpdateFlags.Kill; - else + return; + else // kill case will just merge in m_flags |= updateFlags; // Use the older of the updates as the updateTime - if (Util.EnvironmentTickCountCompare(UpdateTime, update.UpdateTime) > 0) - m_updateTime = update.UpdateTime; + if (Util.EnvironmentTickCountCompare(UpdateTime, oldupdate.UpdateTime) > 0) + m_updateTime = oldupdate.UpdateTime; } public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags) From f387b938598e4a053b23b9267db18e9f5471d847 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 9 Aug 2016 11:59:27 +0100 Subject: [PATCH 04/41] tell prim name on some more ubMeshmerizer error/warn messages --- OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs index bcf8e2b594..6e43cf8054 100644 --- a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs +++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs @@ -417,7 +417,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing meshOsd = (OSDMap)osd; else { - m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap"); + m_log.WarnFormat("[Mesh}: unable to cast mesh asset to OSDMap prim: {0}",primName); return false; } } @@ -451,7 +451,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing if (physicsParms == null) { - m_log.Warn("[MESH]: unknown mesh type"); + m_log.WarnFormat("[MESH]: unknown mesh type for {0}",primName); return false; } From 6c00016447996bc18935edc76bb5d61b6740a296 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 9 Aug 2016 13:18:51 +0100 Subject: [PATCH 05/41] add a simple prim area estimator --- .../Framework/Scenes/SceneObjectPart.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 0847b0b45a..90be18f5e7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1188,6 +1188,29 @@ namespace OpenSim.Region.Framework.Scenes } } + public float maxSimpleArea() + { + float a,b; + if(m_shape.Scale.X > m_shape.Scale.Y) + { + a = m_shape.Scale.X; + if(m_shape.Scale.Y > m_shape.Scale.Z) + b = m_shape.Scale.Y; + else + b = m_shape.Scale.Z; + } + else + { + a = m_shape.Scale.Y; + if(m_shape.Scale.X > m_shape.Scale.Z) + b = m_shape.Scale.X; + else + b = m_shape.Scale.Z; + } + + return a*b; + } + public UpdateRequired UpdateFlag { get; set; } public bool UpdatePhysRequired { get; set; } From 6f5f6431a45cad8e23c2251d661691d905fc08f7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 9 Aug 2016 21:46:19 +0100 Subject: [PATCH 06/41] add a SimpleAngularDistance Updates prioritazition scheme. Results don't look that great so don't use it still. --- .../Region/Framework/Scenes/Prioritizer.cs | 67 ++++++++++++++++++- .../Framework/Scenes/SceneObjectGroup.cs | 17 +++++ .../Framework/Scenes/SceneObjectPart.cs | 24 ++++--- 3 files changed, 97 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index c913ec260b..5669c43b70 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -108,6 +108,9 @@ namespace OpenSim.Region.Framework.Scenes priority = GetPriorityByFrontBack(client, entity); break; */ + case UpdatePrioritizationSchemes.SimpleAngularDistance: + priority = GetPriorityByAngularDistance(client, entity); // TODO: Reimplement SimpleAngularDistance + break; case UpdatePrioritizationSchemes.BestAvatarResponsiveness: default: priority = GetPriorityByBestAvatarResponsiveness(client, entity); @@ -241,7 +244,7 @@ namespace OpenSim.Region.Framework.Scenes */ if (distance > 10f) { - float tmp = (float)Math.Log((double)distance) * 1.4426950408889634073599246810019f - 3.3219280948873623478703194294894f; + float tmp = (float)Math.Log((double)distance) * 1.442695f - 3.321928f; // for a map identical to original: // now // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) @@ -269,5 +272,67 @@ namespace OpenSim.Region.Framework.Scenes return pqueue; } + private uint GetPriorityByAngularDistance(IClientAPI client, ISceneEntity entity) + { + uint pqueue = 2; // keep compiler happy + + ScenePresence presence = m_scene.GetScenePresence(client.AgentId); + if (presence == null) + return PriorityQueue.NumberOfQueues - 1; + + // All avatars other than our own go into pqueue 1 + if (entity is ScenePresence) + return 1; + + if (entity is SceneObjectPart) + { + // Attachments are high priority, + if (((SceneObjectPart)entity).ParentGroup.IsAttachment) + return 2; + + pqueue = ComputeAngleDistancePriority(presence, entity); + + // Non physical prims are lower priority than physical prims + PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; + if (physActor == null || !physActor.IsPhysical) + pqueue++; + } + + return pqueue; + } + + private uint ComputeAngleDistancePriority(ScenePresence presence, ISceneEntity entity) + { + double distance; + + Vector3 presencePos = presence.AbsolutePosition; + + SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; + float bradius = group.GetBoundsRadius(); + Vector3 grppos = group.AbsolutePosition + group.getBoundsCenter(); + distance = Vector3.Distance(presencePos, grppos); + distance -= bradius; + distance *= group.getAreaFactor(); + + // And convert the distance to a priority queue, this computation gives queues + // at 10, 20, 40, 80, 160, 320, 640, and 1280m + uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue + uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; + + if (distance > 10f) + { + float tmp = (float)Math.Log(distance) * 1.442695f - 3.321928f; + // for a map identical to original: + // now + // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) + // 2st constant makes it be log2(distance/10) + + pqueue += (uint)tmp; + if (pqueue > queues - 1) + pqueue = queues - 1; + } + + return pqueue; + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index efc1413a12..e17ef2bded 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1586,12 +1586,22 @@ namespace OpenSim.Region.Framework.Scenes return m_boundsCenter; } + private float m_areaFactor; + public float getAreaFactor() + { + // math is done in GetBoundsRadius(); + if(m_boundsRadius == null) + GetBoundsRadius(); + return m_areaFactor; + } + public float GetBoundsRadius() { // this may need more threading work if(m_boundsRadius == null) { float res = 0; + float areaF = 0; SceneObjectPart p; SceneObjectPart[] parts; float partR; @@ -1613,12 +1623,19 @@ namespace OpenSim.Region.Framework.Scenes } if(partR > res) res = partR; + if(p.maxSimpleArea() > areaF) + areaF = p.maxSimpleArea(); } if(parts.Length > 1) { offset /= parts.Length; // basicly geometric center offset = offset * RootPart.RotationOffset; } + + areaF = 10.0f / areaF; // scale it + areaF = Util.Clamp(areaF, 0.001f, 1000f); // clamp it + + m_areaFactor = (float)Math.Sqrt(areaF); m_boundsCenter = offset; m_boundsRadius = res; return res; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 90be18f5e7..bc603aead0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1191,24 +1191,28 @@ namespace OpenSim.Region.Framework.Scenes public float maxSimpleArea() { float a,b; - if(m_shape.Scale.X > m_shape.Scale.Y) + float sx = m_shape.Scale.X; + float sy = m_shape.Scale.Y; + float sz = m_shape.Scale.Z; + + if( sx > sy) { - a = m_shape.Scale.X; - if(m_shape.Scale.Y > m_shape.Scale.Z) - b = m_shape.Scale.Y; + a = sx; + if(sy > sz) + b = sy; else - b = m_shape.Scale.Z; + b = sz; } else { - a = m_shape.Scale.Y; - if(m_shape.Scale.X > m_shape.Scale.Z) - b = m_shape.Scale.X; + a = sy; + if(sx > sz) + b = sx; else - b = m_shape.Scale.Z; + b = sz; } - return a*b; + return a * b; } public UpdateRequired UpdateFlag { get; set; } From 8fb7a3543f8f15da65a43065020e9ef397b0faaa Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 9 Aug 2016 22:29:11 +0100 Subject: [PATCH 07/41] let physics know about region water level change --- .../CoreModules/World/Estate/EstateManagementModule.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 3ded00c213..56d41a8812 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -572,6 +572,7 @@ namespace OpenSim.Region.CoreModules.World.Estate bool UseEstateSun, bool UseFixedSun, float SunHour, bool UseGlobal, bool EstateFixedSun, float EstateSunHour) { + double lastwaterlevel = Scene.RegionInfo.RegionSettings.WaterHeight; // Water Height Scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight; @@ -584,6 +585,9 @@ namespace OpenSim.Region.CoreModules.World.Estate Scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun; Scene.RegionInfo.RegionSettings.SunPosition = SunHour; + if(Scene.PhysicsEnabled && Scene.PhysicsScene != null && lastwaterlevel != WaterHeight) + Scene.PhysicsScene.SetWaterLevel(WaterHeight); + Scene.TriggerEstateSunUpdate(); //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString()); @@ -1471,7 +1475,7 @@ namespace OpenSim.Region.CoreModules.World.Estate Scene.RegionInfo.EstateSettings.FixedSun, (float)Scene.RegionInfo.EstateSettings.SunPosition); - sendRegionInfoPacketToAll(); +// sendRegionInfoPacketToAll(); already done by setRegionTerrainSettings } From b16d6c030246dd80434815e09c37618efda0e8dc Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 11 Aug 2016 04:52:25 +0100 Subject: [PATCH 08/41] stop renewing xml cache entries expires. Let them expire or grid changes will ignored as long something keeq requesting (like group profiles refreshs). reduce the expire time more ignoring folish config. --- .../XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 83f08e0e4b..88189c9f31 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -1008,11 +1008,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups respData.Add("error", e.ToString()); return respData; } - } - if ((m_cacheTimeout > 0) && (CacheKey != null)) - { - m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout)); + if ((m_cacheTimeout > 0) && (CacheKey != null)) + { + m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(10)); + } } if (resp.Value is Hashtable) From 9aa2484f0d33b8fcce2810bd36b70c9ceb61c2f5 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 11 Aug 2016 08:38:39 +0100 Subject: [PATCH 09/41] to do that don't use slideexpiration; add cap event ChatterBoxForceClose --- .../Linden/Caps/EventQueue/EventQueueGetModule.cs | 10 +++++++++- .../Linden/Caps/EventQueue/EventQueueHelper.cs | 12 ++++++++++++ OpenSim/Region/Framework/Interfaces/IEventQueue.cs | 11 ++++++----- .../XmlRpcGroupsServicesConnectorModule.cs | 2 +- OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs | 5 +++++ 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 6d548ada23..b9038bd6d0 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -372,7 +372,7 @@ namespace OpenSim.Region.ClientStack.Linden caps.RegisterPollHandler( "EventQueueGet", - new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); + new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, Drop, agentID, SERVER_EQ_TIME_NO_EVENTS)); } public bool HasEvents(UUID requestID, UUID agentID) @@ -577,6 +577,14 @@ namespace OpenSim.Region.ClientStack.Linden //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); } + public void ChatterBoxForceClose(UUID toAgent, UUID sessionID, string reason) + { + OSD item = EventQueueHelper.ChatterBoxForceClose(sessionID, reason); + + Enqueue(item, toAgent); + //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); + } + public void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID) { OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesMessage); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs index d552914e81..5e0bd71797 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs @@ -342,6 +342,18 @@ namespace OpenSim.Region.ClientStack.Linden return chatterBoxSessionAgentListUpdates; } + public static OSD ChatterBoxForceClose(UUID sessionID, string reason) + { + OSDMap body = new OSDMap(2); + body.Add("session_id", new OSDUUID(sessionID)); + body.Add("reason", new OSDString(reason)); + + OSDMap chatterBoxForceClose = new OSDMap(2); + chatterBoxForceClose.Add("message", new OSDString("ForceCloseChatterBoxSession")); + chatterBoxForceClose.Add("body", body); + return chatterBoxForceClose; + } + public static OSD GroupMembershipData(UUID receiverAgent, GroupMembershipData[] data) { OSDArray AgentData = new OSDArray(1); diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs index b52576984a..3f54ea5bff 100644 --- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs +++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs @@ -52,11 +52,12 @@ namespace OpenSim.Region.Framework.Interfaces string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY); void ChatterboxInvitation(UUID sessionID, string sessionName, - UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, - uint timeStamp, bool offline, int parentEstateID, Vector3 position, - uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); - void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat, - bool isModerator, bool textMute, bool isEnterorLeave); + UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, + uint timeStamp, bool offline, int parentEstateID, Vector3 position, + uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); + void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, + bool canVoiceChat, bool isModerator, bool textMute, bool isEnterorLeave); + void ChatterBoxForceClose(UUID toAgent, UUID sessionID, string reason); void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); void GroupMembershipData(UUID receiverAgent, GroupMembershipData[] data); OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 88189c9f31..eb64f715a6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -1011,7 +1011,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if ((m_cacheTimeout > 0) && (CacheKey != null)) { - m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(10)); + m_memoryCache.AddOrUpdate(CacheKey, resp, 10.0); } } diff --git a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs index 417efce63c..bc30945dab 100644 --- a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs +++ b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs @@ -152,6 +152,11 @@ namespace OpenSim.Tests.Common AddEvent(toAgent, "ChatterBoxSessionAgentListUpdates", sessionID, fromAgent, canVoiceChat, isModerator, textMute, isEnterorLeave); } + public void ChatterBoxForceClose (UUID toAgent, UUID sessionID, string reason) + { + AddEvent(toAgent, "ForceCloseChatterBoxSession", sessionID, reason); + } + public void ParcelProperties (OpenMetaverse.Messages.Linden.ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID) { AddEvent(avatarID, "ParcelProperties", parcelPropertiesMessage); From cfab2675ffccb81363c59c23ce4c361ad85fe5a6 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 11 Aug 2016 08:42:34 +0100 Subject: [PATCH 10/41] remove code from httptests branch --- .../ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index b9038bd6d0..ba3edd66f7 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -372,7 +372,7 @@ namespace OpenSim.Region.ClientStack.Linden caps.RegisterPollHandler( "EventQueueGet", - new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, Drop, agentID, SERVER_EQ_TIME_NO_EVENTS)); + new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); } public bool HasEvents(UUID requestID, UUID agentID) @@ -582,7 +582,6 @@ namespace OpenSim.Region.ClientStack.Linden OSD item = EventQueueHelper.ChatterBoxForceClose(sessionID, reason); Enqueue(item, toAgent); - //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); } public void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID) From c04792142f332b7d1e892eb739b7e0b70b3bd0e7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 12 Aug 2016 03:58:04 +0100 Subject: [PATCH 11/41] partially revert commit 42a9afdc43cc.. of 06-12 not allowing more updates to be enqueued on deleted objects. Keep the catch up on deenqueue, so preserving the race condition safe guard. Let Scene sendkillObject work even if object is flaged as deleted. Still not clear how this are related to mantis 7858 or even less to 7990. --- .../ClientStack/Linden/UDP/LLClientView.cs | 14 ++----- OpenSim/Region/Framework/Scenes/Scene.cs | 12 ++---- .../Framework/Scenes/SceneObjectGroup.cs | 38 +++++++++---------- .../Framework/Scenes/SceneObjectPart.cs | 3 ++ 4 files changed, 26 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6beb9b42a9..24d92f2eba 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4007,7 +4007,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP bool doCulling = m_scene.ObjectsCullingByDistance; float cullingrange = 64.0f; HashSet GroupsNeedFullUpdate = new HashSet(); - List kills = new List(); // Vector3 mycamera = Vector3.Zero; Vector3 mypos = Vector3.Zero; ScenePresence mysp = (ScenePresence)SceneAgent; @@ -4048,7 +4047,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Instead send another kill object, because the first one may have gotten // into a race condition if (!m_killRecord.Contains(grp.LocalId)) + { m_killRecord.Add(grp.LocalId); + maxUpdatesBytes -= 30; + } continue; } @@ -4336,16 +4338,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_killRecord.Clear(); } - if (kills.Count > 0) - { - foreach(SceneObjectGroup grp in kills) - { - foreach(SceneObjectPart p in grp.Parts) - SendEntityUpdate(p,PrimUpdateFlags.Kill); - } - kills.Clear(); - } - if(GroupsNeedFullUpdate.Count > 0) { foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 33418e631d..5d5ea895ae 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3866,15 +3866,9 @@ namespace OpenSim.Region.Framework.Scenes foreach (uint localID in localIDs) { SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) // It is a prim - { - if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid - { - if (part.ParentGroup.RootPart != part) // Child part - continue; - } - } - deleteIDs.Add(localID); + if (part != null && part.ParentGroup != null && + part.ParentGroup.RootPart == part) + deleteIDs.Add(localID); } ForEachClient(c => c.SendKillObject(deleteIDs)); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index e17ef2bded..df6a1cf00f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2065,41 +2065,37 @@ namespace OpenSim.Region.Framework.Scenes { // We need to keep track of this state in case this group is still queued for backup. IsDeleted = true; - HasGroupChanged = true; DetachFromBackup(); + if(Scene == null) // should not happen unless restart/shutdown ? + return; + SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; - if (Scene != null) + Scene.ForEachScenePresence(delegate(ScenePresence avatar) { - Scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - if (!avatar.IsChildAgent && avatar.ParentID == LocalId) - avatar.StandUp(); + if (!avatar.IsChildAgent && avatar.ParentID == LocalId) + avatar.StandUp(); - if (!silent) + if (!silent) + { + part.ClearUpdateSchedule(); + if (part == m_rootPart) { - part.ClearUpdateSchedule(); - if (part == m_rootPart) + if (!IsAttachment + || AttachedAvatar == avatar.ControllingClient.AgentId + || !HasPrivateAttachmentPoint) { - if (!IsAttachment - || AttachedAvatar == avatar.ControllingClient.AgentId - || !HasPrivateAttachmentPoint) - { - // Send a kill object immediately - avatar.ControllingClient.SendKillObject(new List { part.LocalId }); - // Also, send a terse update; in case race conditions make the object pop again in the client, - // this update will send another kill object - m_rootPart.SendTerseUpdateToClient(avatar.ControllingClient); - } + // Send a kill object immediately + avatar.ControllingClient.SendKillObject(new List { part.LocalId }); } } - }); - } + } + }); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index bc603aead0..ca5951cfac 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -5420,6 +5420,9 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter public void SendTerseUpdateToClient(IClientAPI remoteClient) { + if (ParentGroup.IsDeleted) + return; + if (ParentGroup.IsAttachment && (ParentGroup.RootPart != this || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint)) From 9080aaf9eba71293929627659b83ee77ee4f5d26 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 12 Aug 2016 04:08:19 +0100 Subject: [PATCH 12/41] only reissue a kill if a update is for a deleted sog root part. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 24d92f2eba..2c2bcea17a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1711,11 +1711,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendKillObject(List localIDs) { - // think we do need this // foreach (uint id in localIDs) // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); - // remove pending entities + // remove pending entities to reduce looping chances. lock (m_entityProps.SyncRoot) m_entityProps.Remove(localIDs); lock (m_entityUpdates.SyncRoot) @@ -4046,7 +4045,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Don't send updates for objects that have been marked deleted. // Instead send another kill object, because the first one may have gotten // into a race condition - if (!m_killRecord.Contains(grp.LocalId)) + if (part == grp.RootPart && !m_killRecord.Contains(grp.LocalId)) { m_killRecord.Add(grp.LocalId); maxUpdatesBytes -= 30; From 09832edadf91e02edbc3e5238aad12ec10998391 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 12 Aug 2016 18:47:01 +0100 Subject: [PATCH 13/41] avoid automatic packet spliting in GroupMembersReply --- .../ClientStack/Linden/UDP/LLClientView.cs | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 2c2bcea17a..6275f19199 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4462,12 +4462,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (kills.Count > 0) { + List partIDs = new List(); foreach(SceneObjectGroup grp in kills) { + SendEntityUpdate(grp.RootPart,PrimUpdateFlags.Kill); foreach(SceneObjectPart p in grp.Parts) - SendEntityUpdate(p,PrimUpdateFlags.Kill); + { + if(p != grp.RootPart) + partIDs.Add(p.LocalId); + } } kills.Clear(); + if(partIDs.Count > 0) + { + lock (m_entityProps.SyncRoot) + m_entityProps.Remove(partIDs); + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Remove(partIDs); + } } if(GroupsNeedFullUpdate.Count > 0) @@ -11409,12 +11421,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_GroupsModule.GroupMembersRequest(this, groupMembersRequestPacket.GroupData.GroupID); int memberCount = members.Count; - - while (true) + int indx = 0; + while (indx < memberCount) { - int blockCount = members.Count; - if (blockCount > 40) - blockCount = 40; + int blockCount = memberCount - indx; + if (blockCount > 25) + blockCount = 25; GroupMembersReplyPacket groupMembersReply = (GroupMembersReplyPacket)PacketPool.Instance.GetPacket(PacketType.GroupMembersReply); @@ -11435,8 +11447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blockCount; i++) { - GroupMembersData m = members[0]; - members.RemoveAt(0); + GroupMembersData m = members[indx++]; groupMembersReply.MemberData[i] = new GroupMembersReplyPacket.MemberDataBlock(); @@ -11454,8 +11465,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m.IsOwner; } OutPacket(groupMembersReply, ThrottleOutPacketType.Task); - if (members.Count == 0) - return true; } } return true; From b64f25e631a0ec5681ddff050dc9bead5e0a7c8b Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 13 Aug 2016 00:16:50 +0100 Subject: [PATCH 14/41] add a missing cast to ulong in RegionGridLocToHandle (mantis: 7994) --- OpenSim/Framework/Util.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 5250d30483..96b91fffaf 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -382,7 +382,8 @@ namespace OpenSim.Framework public static ulong RegionGridLocToHandle(uint X, uint Y) { - ulong handle = X << 40; // shift to higher half and mult by 256) + ulong handle = X; + handle <<= 40; // shift to higher half and mult by 256) handle |= (Y << 8); // mult by 256) return handle; } From 7c1b2a5dde3b61dae4cca6bff7d2fe560be96fae Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 13 Aug 2016 05:22:29 +0100 Subject: [PATCH 15/41] add some wiring to have GetUserAccounts for multiple IDs on a single request to grid services. Unfinished, untested --- .../LocalUserAccountServiceConnector.cs | 6 ++ .../RemoteUserAccountServiceConnector.cs | 35 +++++++++ .../SimianUserAccountServiceConnector.cs | 6 ++ .../UserAccountServicesConnector.cs | 72 +++++++++++++++++++ .../HypergridService/UserAccountCache.cs | 6 ++ .../Interfaces/IUserAccountService.cs | 1 + .../UserAccountService/UserAccountService.cs | 13 ++++ 7 files changed, 139 insertions(+) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs index cf9a7b4ddf..1002b8570b 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs @@ -182,6 +182,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts return UserAccountService.GetUserAccount(scopeID, Email); } + public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + { + return UserAccountService.GetUserAccounts(scopeID, IDs, out suported); + } + + public List GetUserAccountsWhere(UUID scopeID, string query) { return null; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs index afbba30547..fb5fae10b1 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs @@ -26,6 +26,8 @@ */ using System; +using System.Collections; +using System.Collections.Generic; using Nini.Config; using log4net; using Mono.Addins; @@ -158,6 +160,39 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts return account; } + public override List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + { + suported = true; + List accs = new List(); + List missing = new List(); + + UUID uuid = UUID.Zero;; + UserAccount account; + bool inCache = false; + + foreach(string id in IDs) + { + if(UUID.TryParse(id, out uuid)) + { + account = m_Cache.Get(uuid, out inCache); + if (inCache) + accs.Add(account); + else + missing.Add(id); + } + } + + if(missing.Count > 0) + { + List ext = base.GetUserAccounts(scopeID, missing, out suported); + if(suported && ext != null) + accs.AddRange(ext); + } + + return accs; + } + + public override bool StoreUserAccount(UserAccount data) { // This remote connector refuses to serve this method diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 563a1e7dda..1ef5ad26c6 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -201,6 +201,12 @@ namespace OpenSim.Services.Connectors.SimianGrid return null; } + public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + { + suported = false; + return null; + } + public bool StoreUserAccount(UserAccount data) { // m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name); diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs index 3de0a20f9e..e6251431e9 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs @@ -191,6 +191,78 @@ namespace OpenSim.Services.Connectors return accounts; } + public virtual List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + { + suported = true; + Dictionary sendData = new Dictionary(); + //sendData["SCOPEID"] = scopeID.ToString(); + sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "getmultiaccounts"; + + sendData["ScopeID"] = scopeID.ToString(); + sendData["IDS"] = new List(IDs); + + string reply = string.Empty; + string reqString = ServerUtils.BuildQueryString(sendData); + string uri = m_ServerURI + "/accounts"; + // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString); + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + uri, + reqString, + m_Auth); + if (reply == null || (reply != null && reply == string.Empty)) + { + m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetMultiUserAccounts received null or empty reply"); + return null; + } + } + catch (Exception e) + { + m_log.DebugFormat("[ACCOUNT CONNECTOR]: Exception when contacting user accounts server at {0}: {1}", uri, e.Message); + } + + List accounts = new List(); + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData != null) + { + if (replyData.ContainsKey("result")) + { + if(replyData["result"].ToString() == "null") + return accounts; + + if(replyData["result"].ToString() == "Failure") + { + suported = false; + return accounts; + } + } + + Dictionary.ValueCollection accountList = replyData.Values; + //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count); + foreach (object acc in accountList) + { + if (acc is Dictionary) + { + UserAccount pinfo = new UserAccount((Dictionary)acc); + accounts.Add(pinfo); + } + else + m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetMultiUserAccounts received invalid response type {0}", + acc.GetType()); + } + } + else + m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetMultiUserAccounts received null response"); + + return accounts; + } + + public void InvalidateCache(UUID userID) { } diff --git a/OpenSim/Services/HypergridService/UserAccountCache.cs b/OpenSim/Services/HypergridService/UserAccountCache.cs index 6c3c6551fd..618bd97d8c 100644 --- a/OpenSim/Services/HypergridService/UserAccountCache.cs +++ b/OpenSim/Services/HypergridService/UserAccountCache.cs @@ -100,6 +100,12 @@ namespace OpenSim.Services.HypergridService return null; } + public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + { + suported = false; + return null; + } + public void InvalidateCache(UUID userID) { m_UUIDCache.Remove(userID); diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs index 18146996a4..19140406d2 100644 --- a/OpenSim/Services/Interfaces/IUserAccountService.cs +++ b/OpenSim/Services/Interfaces/IUserAccountService.cs @@ -187,6 +187,7 @@ namespace OpenSim.Services.Interfaces /// List GetUserAccounts(UUID scopeID, string query); List GetUserAccountsWhere(UUID scopeID, string where); + List GetUserAccounts(UUID scopeID, List IDs, out bool suported); /// /// Store the data given, wich replaces the stored data, therefore must be complete. diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 6010f0c8bd..fbe5e3b68e 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -265,6 +265,19 @@ namespace OpenSim.Services.UserAccountService return MakeUserAccount(d[0]); } + public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + { + suported = true; + List accs = new List(); + UUID uuid = UUID.Zero; + foreach(string id in IDs) + { + if (UUID.TryParse(id, out uuid) && uuid != UUID.Zero) + accs.Add(GetUserAccount(scopeID, uuid)); + } + return accs; + } + public void InvalidateCache(UUID userID) { } From 1337f5f26e628dc7c5d038ffee5e957d95a72566 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 13 Aug 2016 23:41:57 +0100 Subject: [PATCH 16/41] remove a parameter for detection of grid fail to suport getting multiple user accounts per call and handle it where needed. --- .../LocalUserAccountServiceConnector.cs | 4 ++-- .../RemoteUserAccountServiceConnector.cs | 8 +++---- .../SimianUserAccountServiceConnector.cs | 3 +-- .../UserAccountServicesConnector.cs | 22 ++++++++++++++++++- .../HypergridService/UserAccountCache.cs | 3 +-- .../Interfaces/IUserAccountService.cs | 2 +- .../UserAccountService/UserAccountService.cs | 4 ++-- 7 files changed, 31 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs index 1002b8570b..1bb470477c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs @@ -182,9 +182,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts return UserAccountService.GetUserAccount(scopeID, Email); } - public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + public List GetUserAccounts(UUID scopeID, List IDs) { - return UserAccountService.GetUserAccounts(scopeID, IDs, out suported); + return UserAccountService.GetUserAccounts(scopeID, IDs); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs index fb5fae10b1..ce1754f6b1 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs @@ -160,9 +160,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts return account; } - public override List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + public override List GetUserAccounts(UUID scopeID, List IDs) { - suported = true; List accs = new List(); List missing = new List(); @@ -184,15 +183,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts if(missing.Count > 0) { - List ext = base.GetUserAccounts(scopeID, missing, out suported); - if(suported && ext != null) + List ext = base.GetUserAccounts(scopeID, missing); + if(ext != null) accs.AddRange(ext); } return accs; } - public override bool StoreUserAccount(UserAccount data) { // This remote connector refuses to serve this method diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 1ef5ad26c6..6f613c1f5d 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -201,9 +201,8 @@ namespace OpenSim.Services.Connectors.SimianGrid return null; } - public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + public List GetUserAccounts(UUID scopeID, List IDs) { - suported = false; return null; } diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs index e6251431e9..5bc7a1cf80 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs @@ -191,7 +191,27 @@ namespace OpenSim.Services.Connectors return accounts; } - public virtual List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + public virtual List GetUserAccounts(UUID scopeID, List IDs) + { + List accs = new List(); + bool multisuported = true; + accs = doGetMultiUserAccounts(scopeID, IDs, out multisuported); + if(multisuported) + return accs; + + // service does not do multi accounts so need to do it one by one + + UUID uuid = UUID.Zero; + foreach(string id in IDs) + { + if(UUID.TryParse(id, out uuid) && uuid != UUID.Zero) + accs.Add(GetUserAccount(scopeID,uuid)); + } + + return accs; + } + + private List doGetMultiUserAccounts(UUID scopeID, List IDs, out bool suported) { suported = true; Dictionary sendData = new Dictionary(); diff --git a/OpenSim/Services/HypergridService/UserAccountCache.cs b/OpenSim/Services/HypergridService/UserAccountCache.cs index 618bd97d8c..25ffb63548 100644 --- a/OpenSim/Services/HypergridService/UserAccountCache.cs +++ b/OpenSim/Services/HypergridService/UserAccountCache.cs @@ -100,9 +100,8 @@ namespace OpenSim.Services.HypergridService return null; } - public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + public List GetUserAccounts(UUID scopeID, List IDs) { - suported = false; return null; } diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs index 19140406d2..c6f3ef35b0 100644 --- a/OpenSim/Services/Interfaces/IUserAccountService.cs +++ b/OpenSim/Services/Interfaces/IUserAccountService.cs @@ -187,7 +187,7 @@ namespace OpenSim.Services.Interfaces /// List GetUserAccounts(UUID scopeID, string query); List GetUserAccountsWhere(UUID scopeID, string where); - List GetUserAccounts(UUID scopeID, List IDs, out bool suported); + List GetUserAccounts(UUID scopeID, List IDs); /// /// Store the data given, wich replaces the stored data, therefore must be complete. diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index fbe5e3b68e..668fe53730 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -265,9 +265,9 @@ namespace OpenSim.Services.UserAccountService return MakeUserAccount(d[0]); } - public List GetUserAccounts(UUID scopeID, List IDs, out bool suported) + public List GetUserAccounts(UUID scopeID, List IDs) { - suported = true; + // do it one at a time db access should be fast, so no need to break its api List accs = new List(); UUID uuid = UUID.Zero; foreach(string id in IDs) From 57aac3d77e663866b55ffdffc6a775613386aac7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 14 Aug 2016 03:56:44 +0100 Subject: [PATCH 17/41] remove OptionalModules\ViewerSupport\SimulatorFeaturesHelper ShouldSend() since it cannot be used --- .../ViewerSupport/CameraOnlyModeModule.cs | 5 +- .../ViewerSupport/SimulatorFeaturesHelper.cs | 100 +----------------- .../ViewerSupport/SpecialUIModule.cs | 5 +- 3 files changed, 5 insertions(+), 105 deletions(-) diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs index 7ae4223899..770b1f288c 100644 --- a/OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs +++ b/OpenSim/Region/OptionalModules/ViewerSupport/CameraOnlyModeModule.cs @@ -108,8 +108,7 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport { if (m_Enabled) { - IEntityTransferModule et = m_scene.RequestModuleInterface(); - m_Helper = new SimulatorFeaturesHelper(scene, et); + m_Helper = new SimulatorFeaturesHelper(scene); ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface(); if (featuresModule != null) @@ -124,7 +123,7 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) { m_log.DebugFormat("[CAMERA-ONLY MODE]: OnSimulatorFeaturesRequest in {0}", m_scene.RegionInfo.RegionName); - if (m_Helper.ShouldSend(agentID) && m_Helper.UserLevel(agentID) <= m_UserLevel) + if (m_Helper.UserLevel(agentID) <= m_UserLevel) { OSDMap extrasMap; if (features.ContainsKey("OpenSimExtras")) diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs b/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs index 266152238c..1ae18dd870 100644 --- a/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs +++ b/OpenSim/Region/OptionalModules/ViewerSupport/SimulatorFeaturesHelper.cs @@ -53,86 +53,11 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private IEntityTransferModule m_TransferModule; private Scene m_scene; - private struct RegionSend { - public UUID region; - public bool send; - }; - // Using a static cache so that we don't have to perform the time-consuming tests - // in ShouldSend on Extra SimFeatures that go on the same response but come from - // different modules. - // This cached is indexed on the agentID and maps to a list of regions - private static ExpiringCache> m_Cache = new ExpiringCache>(); - private const double TIMEOUT = 1.0; // time in cache - - public SimulatorFeaturesHelper(Scene scene, IEntityTransferModule et) + public SimulatorFeaturesHelper(Scene scene) { m_scene = scene; - m_TransferModule = et; - } - - public bool ShouldSend(UUID agentID) - { - List rsendlist; - RegionSend rsend; - if (m_Cache.TryGetValue(agentID, out rsendlist)) - { - rsend = rsendlist.Find(r => r.region == m_scene.RegionInfo.RegionID); - if (rsend.region != UUID.Zero) // Found it - { - return rsend.send; - } - } - - // Relatively complex logic for deciding whether to send the extra SimFeature or not. - // This is because the viewer calls this cap to all sims that it knows about, - // including the departing sims and non-neighbors (those that are cached). - rsend.region = m_scene.RegionInfo.RegionID; - rsend.send = false; - IClientAPI client = null; - int counter = 200; - - // Let's wait a little to see if we get a client here - while (!m_scene.TryGetClient(agentID, out client) && counter-- > 0) - Thread.Sleep(50); - - if (client != null) - { - ScenePresence sp = WaitGetScenePresence(agentID); - - if (sp != null) - { - // On the receiving region, the call to this cap may arrive before - // the agent is root. Make sure we only proceed from here when the agent - // has been made root - counter = 200; - while ((sp.IsInTransit || sp.IsChildAgent) && counter-- > 0) - { - Thread.Sleep(50); - } - - // The viewer calls this cap on the departing sims too. Make sure - // that we only proceed after the agent is not in transit anymore. - // The agent must be root and not going anywhere - if (!sp.IsChildAgent && !m_TransferModule.IsInTransit(agentID)) - rsend.send = true; - - } - } - //else - // m_log.DebugFormat("[XXX]: client is null"); - - - if (rsendlist == null) - { - rsendlist = new List(); - m_Cache.AddOrUpdate(agentID, rsendlist, TIMEOUT); - } - rsendlist.Add(rsend); - - return rsend.send; } public int UserLevel(UUID agentID) @@ -144,28 +69,5 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport return level; } - - protected virtual ScenePresence WaitGetScenePresence(UUID agentID) - { - int ntimes = 20; - ScenePresence sp = null; - while ((sp = m_scene.GetScenePresence(agentID)) == null && (ntimes-- > 0)) - Thread.Sleep(1000); - - if (sp == null) - m_log.WarnFormat( - "[XXX]: Did not find presence with id {0} in {1} before timeout", - agentID, m_scene.RegionInfo.RegionName); - else - { - ntimes = 10; - while (sp.IsInTransit && (ntimes-- > 0)) - Thread.Sleep(1000); - } - - return sp; - } - } - } diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs index 3fe922df9c..fa8fc66c31 100644 --- a/OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs +++ b/OpenSim/Region/OptionalModules/ViewerSupport/SpecialUIModule.cs @@ -102,8 +102,7 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport { if (m_Enabled) { - IEntityTransferModule et = m_scene.RequestModuleInterface(); - m_Helper = new SimulatorFeaturesHelper(scene, et); + m_Helper = new SimulatorFeaturesHelper(scene); ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface(); if (featuresModule != null) @@ -118,7 +117,7 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) { m_log.DebugFormat("[SPECIAL UI]: OnSimulatorFeaturesRequest in {0}", m_scene.RegionInfo.RegionName); - if (m_Helper.ShouldSend(agentID) && m_Helper.UserLevel(agentID) <= m_UserLevel) + if (m_Helper.UserLevel(agentID) <= m_UserLevel) { OSDMap extrasMap; OSDMap specialUI = new OSDMap(); From 5dfb706bea7d190fef01691fad21f726b8bacaa2 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 16 Aug 2016 01:50:06 +0100 Subject: [PATCH 18/41] fix llVolumeDetect(FALSE) not working --- .../Framework/Scenes/SceneObjectPart.cs | 58 ++----------------- 1 file changed, 5 insertions(+), 53 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ca5951cfac..6f2a1de55e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4741,9 +4741,11 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter VolumeDetectActive = SetVD; - // volume detector implies phantom + // volume detector implies phantom we need to decouple this mess if (VolumeDetectActive) SetPhantom = true; + else if(wasVD) + SetPhantom = false; if (UsePhysics) AddFlag(PrimFlags.Physics); @@ -4760,7 +4762,6 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter else RemFlag(PrimFlags.TemporaryOnRez); - if (ParentGroup.Scene == null) return; @@ -4790,26 +4791,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter { AddToPhysics(UsePhysics, SetPhantom, building, false); pa = PhysActor; -/* - if (pa != null) - { - if ( -// ((AggregateScriptEvents & scriptEvents.collision) != 0) || -// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || -// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || -// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || -// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || -// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || - ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || - ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || - (CollisionSound != UUID.Zero) - ) - { - pa.OnCollisionUpdate += PhysicsCollision; - pa.SubscribeEvents(1000); - } - } -*/ + if (pa != null) { pa.SetMaterial(Material); @@ -4820,12 +4802,6 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter { DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. -/* moved into DoPhysicsPropertyUpdate - if(VolumeDetectActive) - pa.SetVolumeDetect(1); - else - pa.SetVolumeDetect(0); -*/ if (pa.Building != building) pa.Building = building; @@ -4834,32 +4810,8 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter UpdatePhysicsSubscribedEvents(); } } - if (SetVD) - { - // If the above logic worked (this is urgent candidate to unit tests!) - // we now have a physicsactor. - // Defensive programming calls for a check here. - // Better would be throwing an exception that could be catched by a unit test as the internal - // logic should make sure, this Physactor is always here. - if (pa != null) - { - pa.SetVolumeDetect(1); - AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active - VolumeDetectActive = true; - } - // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); - } - else if (SetVD != wasVD) - { - // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like - // (mumbles, well, at least if you have infinte CPU powers :-)) - if (pa != null) - pa.SetVolumeDetect(0); - RemFlag(PrimFlags.Phantom); - VolumeDetectActive = false; - } - // and last in case we have a new actor and not building + // and last in case we have a new actor and not building if (ParentGroup != null) { From 41062c16273cb07f90dc282e4379dd649782988a Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 16 Aug 2016 04:21:49 +0100 Subject: [PATCH 19/41] fix misspelled message mantis: 7996 --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 5d5ea895ae..d5dbcaf7d1 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4452,7 +4452,7 @@ Label_GroupsDone: { m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to private region {0}: You are do not have access to that region.", + reason = String.Format("Denied access to private region {0}: You do not have access to that region.", RegionInfo.RegionName); return false; } From a997ffd497a9bb11e23538ea8242ffedcfdeab5c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 16 Aug 2016 04:35:49 +0100 Subject: [PATCH 20/41] sync osForceAttachToOtherAvatarFromInventory thread level in code and in osslEnable.ini mantis: 7997 --- bin/config-include/osslEnable.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/config-include/osslEnable.ini b/bin/config-include/osslEnable.ini index c87539fe79..4c6be1604c 100644 --- a/bin/config-include/osslEnable.ini +++ b/bin/config-include/osslEnable.ini @@ -213,6 +213,7 @@ ; Some of these were added as early functionality for NPCs. This has been replaced with the NPC functions. Allow_osAvatarPlayAnimation = false Allow_osAvatarStopAnimation = false + Allow_osForceAttachToOtherAvatarFromInventory = false Allow_osForceDetachFromAvatar = false Allow_osForceOtherSit = false ; The notecard functions can cause a lot of load on the region if over used @@ -225,7 +226,6 @@ ; ThreatLevel Severe Allow_osConsoleCommand = false - Allow_osForceAttachToOtherAvatarFromInventory = false Allow_osGrantScriptPermissions = false Allow_osKickAvatar = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osRevokeScriptPermissions = false From 1c1d40cf6a0d40f510607b834416dc10ec318db4 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 16 Aug 2016 05:04:44 +0100 Subject: [PATCH 21/41] libOMV PrimFlags.JointLP2P does not exist. Its bit now means VolumeDetector. VolumeDetectActive is now stored on that flag bit. with this change it is now sent to viewers that now gray out phantom on object edit. At same time fixes the fact volumedetector was not been saved on region db and so was lost on restarts. libOMV needs to be fix on this and other PrimFlags --- .../Framework/Scenes/SceneObjectPart.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 6f2a1de55e..459b01eb3f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -285,7 +285,23 @@ namespace OpenSim.Region.Framework.Scenes // but reversed logic: bit cleared means free to rotate public byte RotationAxisLocks = 0; - public bool VolumeDetectActive; + // WRONG flag in libOmvPrimFlags + private const uint primFlagVolumeDetect = (uint)PrimFlags.JointLP2P; + + public bool VolumeDetectActive + { + get + { + return (Flags & (PrimFlags)primFlagVolumeDetect) != 0; + } + set + { + if(value) + Flags |= (PrimFlags)primFlagVolumeDetect; + else + Flags &= (PrimFlags)(~primFlagVolumeDetect); + } + } public bool IsWaitingForFirstSpinUpdatePacket; @@ -4742,7 +4758,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter VolumeDetectActive = SetVD; // volume detector implies phantom we need to decouple this mess - if (VolumeDetectActive) + if (SetVD) SetPhantom = true; else if(wasVD) SetPhantom = false; From 544b859c007c6062cf2a962d7180b27be5ad05ec Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 16 Aug 2016 05:20:46 +0100 Subject: [PATCH 22/41] fix tests acording --- .../Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs index 1737e3c40c..e98e63177f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs @@ -107,7 +107,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests m_so1.ScriptSetVolumeDetect(true); // Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags); - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom)); + // PrimFlags.JointLP2P is incorrect it now means VolumeDetect (as defined by viewers) + Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.JointLP2P)); m_so1.ScriptSetVolumeDetect(false); @@ -146,7 +147,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests m_so1.ScriptSetPhysicsStatus(true); m_so1.ScriptSetVolumeDetect(true); - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics)); + // PrimFlags.JointLP2P is incorrect it now means VolumeDetect (as defined by viewers) + Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics | PrimFlags.JointLP2P)); m_so1.ScriptSetVolumeDetect(false); From 72876fc68385861e06fd900707c3a7c28d040a7d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 16 Aug 2016 23:11:01 +0100 Subject: [PATCH 23/41] drasticly reduce HG inventory caches Expire times, Remove them all onClientClose. This to avoid potencial desyncs with inventory service --- .../Inventory/HGInventoryBroker.cs | 19 ++++++++++--------- .../Inventory/InventoryCache.cs | 13 ++++++++++++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 863560b5e2..c48186fdab 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -203,21 +203,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory void OnClientClosed(UUID clientID, Scene scene) { - if (m_InventoryURLs.ContainsKey(clientID)) // if it's in cache + ScenePresence sp = null; + foreach (Scene s in m_Scenes) { - ScenePresence sp = null; - foreach (Scene s in m_Scenes) + s.TryGetScenePresence(clientID, out sp); + if ((sp != null) && !sp.IsChildAgent && (s != scene)) { - s.TryGetScenePresence(clientID, out sp); - if ((sp != null) && !sp.IsChildAgent && (s != scene)) - { - m_log.DebugFormat("[INVENTORY CACHE]: OnClientClosed in {0}, but user {1} still in sim. Keeping inventoryURL in cache", + m_log.DebugFormat("[INVENTORY CACHE]: OnClientClosed in {0}, but user {1} still in sim. Keeping inventoryURL in cache", scene.RegionInfo.RegionName, clientID); return; - } } - DropInventoryServiceURL(clientID); } + + if (m_InventoryURLs.ContainsKey(clientID)) // if it's in cache + DropInventoryServiceURL(clientID); + + m_Cache.RemoveAll(clientID); } /// diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs index 3195e6b872..f7ef2eaa53 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs @@ -38,12 +38,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory /// public class InventoryCache { - private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour + private const double CACHE_EXPIRATION_SECONDS = 60.0; // 1 minute private static ExpiringCache m_RootFolders = new ExpiringCache(); private static ExpiringCache> m_FolderTypes = new ExpiringCache>(); private static ExpiringCache m_Inventories = new ExpiringCache(); + + public void RemoveAll(UUID userID) + { + if(m_RootFolders.Contains(userID)) + m_RootFolders.Remove(userID); + if(m_FolderTypes.Contains(userID)) + m_FolderTypes.Remove(userID); + if(m_Inventories.Contains(userID)) + m_Inventories.Remove(userID); + } + public void Cache(UUID userID, InventoryFolderBase root) { m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS); From 04ea34f379a1839e618ef1a7ba05a1be19f8e43c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 17 Aug 2016 06:00:42 +0100 Subject: [PATCH 24/41] add GetUsersNames(string[] ids) to UserManagement. Make GetDisplayNames cap use it so several IDs are handle on a single call. Since there is no grid side suport, no much gain still --- .../GetDisplayNames/GetDisplayNamesHandler.cs | 58 ++++----- .../GetDisplayNamesServerConnector.cs | 2 - .../UserManagement/UserManagementModule.cs | 116 +++++++++++++++++- .../RemoteUserAccountServiceConnector.cs | 2 +- .../Services/Interfaces/IUserManagement.cs | 1 + 5 files changed, 143 insertions(+), 36 deletions(-) diff --git a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs index 155196c5b6..3e01bbb756 100644 --- a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs @@ -29,8 +29,6 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; -using System.Drawing; -using System.Drawing.Imaging; using System.Reflection; using System.IO; using System.Web; @@ -38,12 +36,7 @@ using log4net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; -using OpenMetaverse.Imaging; -using OpenSim.Framework; -using OpenSim.Framework.Capabilities; -using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.Framework.Interfaces; using OpenSim.Services.Interfaces; using Caps = OpenSim.Framework.Capabilities.Caps; using OSDMap = OpenMetaverse.StructuredData.OSDMap; @@ -70,7 +63,6 @@ namespace OpenSim.Capabilities.Handlers NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); string[] ids = query.GetValues("ids"); - if (m_UserManagement == null) { m_log.Error("[GET_DISPLAY_NAMES]: Cannot fetch display names without a user management component"); @@ -78,35 +70,39 @@ namespace OpenSim.Capabilities.Handlers return new byte[0]; } + Dictionary names = m_UserManagement.GetUsersNames(ids); + OSDMap osdReply = new OSDMap(); OSDArray agents = new OSDArray(); osdReply["agents"] = agents; - foreach (string id in ids) + foreach (KeyValuePair kvp in names) { - UUID uuid = UUID.Zero; - if (UUID.TryParse(id, out uuid)) - { - string name = m_UserManagement.GetUserName(uuid); - if (!string.IsNullOrEmpty(name)) - { - string[] parts = name.Split(new char[] {' '}); - OSDMap osdname = new OSDMap(); - // a date that is valid -// osdname["display_name_next_update"] = OSD.FromDate(new DateTime(1970,1,1)); - // but send one that blocks edition, since we actually don't suport this - osdname["display_name_next_update"] = OSD.FromDate(DateTime.UtcNow.AddDays(8)); - osdname["display_name_expires"] = OSD.FromDate(DateTime.UtcNow.AddMonths(1)); - osdname["display_name"] = OSD.FromString(name); - osdname["legacy_first_name"] = parts[0]; - osdname["legacy_last_name"] = parts[1]; - osdname["username"] = OSD.FromString(name); - osdname["id"] = OSD.FromUUID(uuid); - osdname["is_display_name_default"] = OSD.FromBoolean(true); + if (string.IsNullOrEmpty(kvp.Value)) + continue; + if(kvp.Key == UUID.Zero) + continue; - agents.Add(osdname); - } + string[] parts = kvp.Value.Split(new char[] {' '}); + OSDMap osdname = new OSDMap(); + if(parts[0] == "Unknown") + { + osdname["display_name_next_update"] = OSD.FromDate(DateTime.UtcNow.AddHours(1)); + osdname["display_name_expires"] = OSD.FromDate(DateTime.UtcNow.AddHours(2)); } + else + { + osdname["display_name_next_update"] = OSD.FromDate(DateTime.UtcNow.AddDays(8)); + osdname["display_name_expires"] = OSD.FromDate(DateTime.UtcNow.AddMonths(1)); + } + osdname["display_name"] = OSD.FromString(kvp.Value); + osdname["legacy_first_name"] = parts[0]; + osdname["legacy_last_name"] = parts[1]; + osdname["username"] = OSD.FromString(kvp.Value); + osdname["id"] = OSD.FromUUID(kvp.Key); + osdname["is_display_name_default"] = OSD.FromBoolean(true); + + agents.Add(osdname); } // Full content request @@ -116,8 +112,6 @@ namespace OpenSim.Capabilities.Handlers string reply = OSDParser.SerializeLLSDXmlString(osdReply); return System.Text.Encoding.UTF8.GetBytes(reply); - } - } } diff --git a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs index d42de56e9f..8f70c97880 100644 --- a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs +++ b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesServerConnector.cs @@ -61,8 +61,6 @@ namespace OpenSim.Capabilities.Handlers if (m_UserManagement == null) throw new Exception(String.Format("Failed to load UserManagement from {0}; config is {1}", umService, m_ConfigName)); - - string rurl = serverConfig.GetString("GetTextureRedirectURL"); server.AddStreamHandler( new GetDisplayNamesHandler("/CAPS/agents/", m_UserManagement, "GetDisplayNames", null)); diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index b72593cad9..2fd9183198 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -481,6 +481,121 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return user.FirstName + " " + user.LastName; } + public virtual Dictionary GetUsersNames(string[] ids) + { + Dictionary ret = new Dictionary(); + if(m_Scenes.Count <= 0) + return ret; + + List missing = new List(); + + // look in cache + UserData userdata = new UserData(); + UUID uuid = UUID.Zero; + foreach(string id in ids) + { + if(UUID.TryParse(id, out uuid)) + { + lock (m_UserCache) + { + if (m_UserCache.TryGetValue(uuid, out userdata) && + userdata.HasGridUserTried && + userdata.FirstName != "Unknown") + { + string name = userdata.FirstName + " " + userdata.LastName; + ret[uuid] = name; + } + else + missing.Add(id); + } + } + } + + if(missing.Count == 0) + return ret; + + // try user account service + List accounts = m_Scenes[0].UserAccountService.GetUserAccounts( + m_Scenes[0].RegionInfo.ScopeID, missing); + + if(accounts.Count != 0) + { + foreach(UserAccount uac in accounts) + { + if(uac != null) + { + string name = uac.FirstName + " " + uac.LastName; + ret[uac.PrincipalID] = name; + missing.Remove(uac.PrincipalID.ToString()); // slowww + + userdata = new UserData(); + userdata.Id = uac.PrincipalID; + userdata.FirstName = uac.FirstName; + userdata.LastName = uac.LastName; + userdata.HomeURL = string.Empty; + userdata.IsUnknownUser = false; + userdata.HasGridUserTried = true; + lock (m_UserCache) + m_UserCache[uac.PrincipalID] = userdata; + } + } + } + + if (missing.Count == 0 || m_Scenes[0].GridUserService == null) + return ret; + + // try grid user service + + GridUserInfo[] pinfos = m_Scenes[0].GridUserService.GetGridUserInfo(missing.ToArray()); + if(pinfos.Length > 0) + { + foreach(GridUserInfo uInfo in pinfos) + { + if (uInfo != null) + { + string url, first, last, tmp; + UUID u; + if(uInfo.UserID.Length <= 36) + continue; + + if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp)) + { + if (url != string.Empty) + { + try + { + string name = first.Replace(" ", ".") + "." + last.Replace(" ", ".") + " @" + new Uri(url).Authority; + ret[u] = name; + missing.Remove(u.ToString()); + } + catch + { + } + } + } + } + } + } + + // add the UMMthings ( not sure we should) + if(missing.Count > 0) + { + foreach(string id in missing) + { + if(UUID.TryParse(id, out uuid) && uuid != UUID.Zero) + { + if (m_Scenes[0].LibraryService != null && + (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) + ret[uuid] = "Mr OpenSim"; + else + ret[uuid] = "Unknown UserUMMAU43"; + } + } + } + + return ret; + } + public virtual string GetUserHomeURL(UUID userID) { UserData user; @@ -584,7 +699,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement else { userdata = new UserData(); - userdata.HasGridUserTried = false; userdata.Id = uuid; userdata.FirstName = "Unknown"; userdata.LastName = "UserUMMAU42"; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs index ce1754f6b1..90c90d6f1b 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs @@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts List accs = new List(); List missing = new List(); - UUID uuid = UUID.Zero;; + UUID uuid = UUID.Zero; UserAccount account; bool inCache = false; diff --git a/OpenSim/Services/Interfaces/IUserManagement.cs b/OpenSim/Services/Interfaces/IUserManagement.cs index 9e560d5f89..225560e00b 100644 --- a/OpenSim/Services/Interfaces/IUserManagement.cs +++ b/OpenSim/Services/Interfaces/IUserManagement.cs @@ -42,6 +42,7 @@ namespace OpenSim.Services.Interfaces string GetUserUUI(UUID uuid); bool GetUserUUI(UUID userID, out string uui); string GetUserServerURL(UUID uuid, string serverType); + Dictionary GetUsersNames(string[] ids); /// /// Get user ID by the given name. From 9f88273741cbe2bb46535fd0061258bbc695a121 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 17 Aug 2016 06:24:58 +0100 Subject: [PATCH 25/41] add GetMultiAccounts USER SERVICE HANDLER. UNTESTED !!! --- .../UserAccountServerPostHandler.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs index 21eb790643..9efe741b94 100644 --- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs +++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs @@ -103,6 +103,8 @@ namespace OpenSim.Server.Handlers.UserAccounts return GetAccount(request); case "getaccounts": return GetAccounts(request); + case "getmultiaccounts": + return GetMultiAccounts(request); case "setaccount": if (m_AllowSetAccount) return StoreAccount(request); @@ -201,6 +203,50 @@ namespace OpenSim.Server.Handlers.UserAccounts return Util.UTF8NoBomEncoding.GetBytes(xmlString); } + byte[] GetMultiAccounts(Dictionary request) + { + UUID scopeID = UUID.Zero; + if (request.ContainsKey("ScopeID") && !UUID.TryParse(request["ScopeID"].ToString(), out scopeID)) + return FailureResult(); + + if (!request.ContainsKey("IDS")) + { + m_log.DebugFormat("[USER SERVICE HANDLER]: GetMultiAccounts called without required uuids argument"); + return FailureResult(); + } + + if (!(request["IDS"] is List)) + { + m_log.DebugFormat("[USER SERVICE HANDLER]: GetMultiAccounts input argument was of unexpected type {0}", request["IDS"].GetType().ToString()); + return FailureResult(); + } + + List userIDs = (List)request["IDS"]; + + List accounts = m_UserAccountService.GetUserAccounts(scopeID, userIDs); + + Dictionary result = new Dictionary(); + if ((accounts == null) || ((accounts != null) && (accounts.Count == 0))) + { + result["result"] = "null"; + } + else + { + int i = 0; + foreach (UserAccount acc in accounts) + { + Dictionary rinfoDict = acc.ToKeyValuePairs(); + result["account" + i] = rinfoDict; + i++; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + + //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString); + return Util.UTF8NoBomEncoding.GetBytes(xmlString); + } + byte[] StoreAccount(Dictionary request) { UUID principalID = UUID.Zero; From e9638ee9e90bc596c6c1cb54c58d18e16f3c0481 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 17 Aug 2016 20:26:01 +0100 Subject: [PATCH 26/41] increase physics collisions report rate back to 20/s --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 459b01eb3f..b3c643dcca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -5254,7 +5254,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter { // subscribe to physics updates. pa.OnCollisionUpdate += PhysicsCollision; - pa.SubscribeEvents(100); // 10 reports per second + pa.SubscribeEvents(50); // 20 reports per second } else { From bca5fd98dc0af5fdf4879a46c2a08c2c462bf4ff Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 17 Aug 2016 21:20:20 +0100 Subject: [PATCH 27/41] remove some dead code --- .../Framework/Scenes/SceneObjectPart.cs | 242 +----------------- 1 file changed, 2 insertions(+), 240 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b3c643dcca..01a323ee9e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2121,12 +2121,6 @@ namespace OpenSim.Region.Framework.Scenes if (localGlobalTF) { -/* - Quaternion grot = GetWorldRotation(); - Quaternion AXgrot = grot; - Vector3 AXimpulsei = impulsei; - Vector3 newimpulse = AXimpulsei * AXgrot; - */ torque *= GetWorldRotation(); } @@ -2265,16 +2259,8 @@ namespace OpenSim.Region.Framework.Scenes if (userExposed) { -/* - if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) - { - ParentGroup.Scene.AssetService.Get( - dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived); - } -*/ bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); dupe.DoPhysicsPropertyUpdate(UsePhysics, true); -// dupe.UpdatePhysicsSubscribedEvents(); // not sure... } if (dupe.PhysActor != null) @@ -2287,23 +2273,6 @@ namespace OpenSim.Region.Framework.Scenes return dupe; } - /// - /// Called back by asynchronous asset fetch. - /// - /// ID of asset received - /// Register - /// -/* - protected void AssetReceived(string id, Object sender, AssetBase asset) - { - if (asset != null) - SculptTextureCallback(asset); -// else -// m_log.WarnFormat( -// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", -// Name, UUID, id); - } -*/ /// /// Do a physics property update for a NINJA joint. /// @@ -3285,39 +3254,6 @@ namespace OpenSim.Region.Framework.Scenes ParentGroup.ScriptSetPhysicsStatus(UsePhysics); } - /// - /// Set sculpt and mesh data, and tell the physics engine to process the change. - /// - /// The mesh itself. -/* - public void SculptTextureCallback(AssetBase texture) - { - if (m_shape.SculptEntry) - { - // commented out for sculpt map caching test - null could mean a cached sculpt map has been found - //if (texture != null) - { - if (texture != null) - { -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Setting sculpt data for {0} on SculptTextureCallback()", Name); - - m_shape.SculptData = texture.Data; - } - - PhysicsActor pa = PhysActor; - - if (pa != null) - { - // Update the physics actor with the new loaded sculpt data and set the taint signal. - pa.Shape = m_shape; - - ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); - } - } - } - } -*/ /// /// Send a full update to the client for the given part /// @@ -4058,103 +3994,6 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter } } - public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot) - { - // In this case we're using a sphere with a radius of the largest dimension of the prim - // TODO: Change to take shape into account - - EntityIntersection result = new EntityIntersection(); - Vector3 vAbsolutePosition = AbsolutePosition; - Vector3 vScale = Scale; - Vector3 rOrigin = iray.Origin; - Vector3 rDirection = iray.Direction; - - //rDirection = rDirection.Normalize(); - // Buidling the first part of the Quadratic equation - Vector3 r2ndDirection = rDirection*rDirection; - float itestPart1 = r2ndDirection.X + r2ndDirection.Y + r2ndDirection.Z; - - // Buidling the second part of the Quadratic equation - Vector3 tmVal2 = rOrigin - vAbsolutePosition; - Vector3 r2Direction = rDirection*2.0f; - Vector3 tmVal3 = r2Direction*tmVal2; - - float itestPart2 = tmVal3.X + tmVal3.Y + tmVal3.Z; - - // Buidling the third part of the Quadratic equation - Vector3 tmVal4 = rOrigin*rOrigin; - Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition; - - Vector3 tmVal6 = vAbsolutePosition*rOrigin; - - // Set Radius to the largest dimension of the prim - float radius = 0f; - if (vScale.X > radius) - radius = vScale.X; - if (vScale.Y > radius) - radius = vScale.Y; - if (vScale.Z > radius) - radius = vScale.Z; - - // the second part of this is the default prim size - // once we factor in the aabb of the prim we're adding we can - // change this to; - // radius = (radius / 2) - 0.01f; - // - radius = (radius / 2) + (0.5f / 2) - 0.1f; - - //radius = radius; - - float itestPart3 = tmVal4.X + tmVal4.Y + tmVal4.Z + tmVal5.X + tmVal5.Y + tmVal5.Z - - (2.0f*(tmVal6.X + tmVal6.Y + tmVal6.Z + (radius*radius))); - - // Yuk Quadradrics.. Solve first - float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3); - if (rootsqr < 0.0f) - { - // No intersection - return result; - } - float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); - - if (root < 0.0f) - { - // perform second quadratic root solution - root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); - - // is there any intersection? - if (root < 0.0f) - { - // nope, no intersection - return result; - } - } - - // We got an intersection. putting together an EntityIntersection object with the - // intersection information - Vector3 ipoint = - new Vector3(iray.Origin.X + (iray.Direction.X*root), iray.Origin.Y + (iray.Direction.Y*root), - iray.Origin.Z + (iray.Direction.Z*root)); - - result.HitTF = true; - result.ipoint = ipoint; - - // Normal is calculated by the difference and then normalizing the result - Vector3 normalpart = ipoint - vAbsolutePosition; - result.normal = normalpart / normalpart.Length(); - - // It's funny how the Vector3 object has a Distance function, but the Axiom.Math object doesn't. - // I can write a function to do it.. but I like the fact that this one is Static. - - Vector3 distanceConvert1 = new Vector3(iray.Origin.X, iray.Origin.Y, iray.Origin.Z); - Vector3 distanceConvert2 = new Vector3(ipoint.X, ipoint.Y, ipoint.Z); - float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2); - - result.distance = distance; - - return result; - } - public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters) { // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes @@ -4522,15 +4361,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter public void UpdateExtraParam(ushort type, bool inUse, byte[] data) { m_shape.ReadInUpdateExtraParam(type, inUse, data); -/* - if (type == 0x30) - { - if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero) - { - ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived); - } - } -*/ + if (ParentGroup != null) { ParentGroup.HasGroupChanged = true; @@ -5088,42 +4919,6 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter } } - /// - /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics - /// engine can use it. - /// - /// - /// When the physics engine has finished with it, the sculpt data is discarded to save memory. - /// -/* - public void CheckSculptAndLoad() - { -// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); - - return; - - if (ParentGroup.IsDeleted) - return; - - if ((ParentGroup.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) - return; - - if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero) - { - // check if a previously decoded sculpt map has been cached - // We don't read the file here - the meshmerizer will do that later. - // TODO: Could we simplify the meshmerizer code by reading and setting the data here? - if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString()))) - { - SculptTextureCallback(null); - } - else - { - ParentGroup.Scene.AssetService.Get(Shape.SculptTexture.ToString(), this, AssetReceived); - } - } - } -*/ /// /// Update the texture entry for this part. /// @@ -5299,41 +5094,8 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter { objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; } -/* - PhysicsActor pa = PhysActor; - if (pa != null) - { - if ( -// ((AggregateScriptEvents & scriptEvents.collision) != 0) || -// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || -// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || -// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || -// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || -// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || - ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero) - ) - { - // subscribe to physics updates. - pa.OnCollisionUpdate += PhysicsCollision; - pa.SubscribeEvents(1000); - } - else - { - pa.UnSubscribeEvents(); - pa.OnCollisionUpdate -= PhysicsCollision; - } - } - */ - UpdatePhysicsSubscribedEvents(); - //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) - //{ - // ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting; - //} - //else - //{ - // ParentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting; - //} + UpdatePhysicsSubscribedEvents(); LocalFlags = (PrimFlags)objectflagupdate; From f1495cb237d23955a3bba32d9c6978bca4943026 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 17 Aug 2016 22:34:21 +0100 Subject: [PATCH 28/41] ubOde reduce collision_start latency in same cases (only one collision happening and more than 50ms since last) --- OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs | 5 ++--- OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs | 13 ++++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs index cef7063a2d..c9489d2622 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs @@ -1605,18 +1605,17 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (m_cureventsubscription < m_eventsubscription) return; - m_cureventsubscription = 0; - int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; if (!SentEmptyCollisionsEvent || ncolisions > 0) { base.SendCollisionUpdate(CollisionEventsThisFrame); + m_cureventsubscription = 0; if (ncolisions == 0) { SentEmptyCollisionsEvent = true; - _parent_scene.RemoveCollisionEventReporting(this); +// _parent_scene.RemoveCollisionEventReporting(this); } else { diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs index 9f62644f67..6f2cbbe5b2 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs @@ -1000,9 +1000,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { - if (CollisionEventsThisFrame == null) CollisionEventsThisFrame = new CollisionEventUpdate(); + CollisionEventsThisFrame.AddCollider(CollidedWith, contact); _parent_scene.AddCollisionEventReporting(this); } @@ -1033,28 +1033,27 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (CollisionEventsThisFrame == null) return; + int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; + if (m_cureventsubscription < m_eventsubscription) return; - m_cureventsubscription = 0; - - int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; - if (!SentEmptyCollisionsEvent || ncolisions > 0) { base.SendCollisionUpdate(CollisionEventsThisFrame); + m_cureventsubscription = 0; if (ncolisions == 0) { SentEmptyCollisionsEvent = true; - _parent_scene.RemoveCollisionEventReporting(this); +// _parent_scene.RemoveCollisionEventReporting(this); } else if(Body == IntPtr.Zero || d.BodyIsEnabled(Body)) { SentEmptyCollisionsEvent = false; CollisionEventsThisFrame.Clear(); } - } + } } public override bool SubscribedEvents() From 7d968213fdae2548675833bc42e4863f8967e3cc Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 17 Aug 2016 23:33:11 +0100 Subject: [PATCH 29/41] fix region Allow damage and parcel safe flags handling --- OpenSim/Region/CoreModules/World/Land/LandObject.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index b00f2b0de3..69a34550a9 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -374,9 +374,10 @@ namespace OpenSim.Region.CoreModules.World.Land public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) { - remote_client.SceneAgent.Invulnerable = - !m_scene.RegionInfo.RegionSettings.AllowDamage || - (m_landData.Flags & (uint)ParcelFlags.AllowDamage) == 0; + if(m_scene.RegionInfo.RegionSettings.AllowDamage) + remote_client.SceneAgent.Invulnerable = false; + else + remote_client.SceneAgent.Invulnerable = (m_landData.Flags & (uint)ParcelFlags.AllowDamage) == 0; if (remote_client.SceneAgent.PresenceType == PresenceType.Npc) return; @@ -779,11 +780,10 @@ namespace OpenSim.Region.CoreModules.World.Land { if (over.LandData.LocalID == LandData.LocalID) { - if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && - m_scene.RegionInfo.RegionSettings.AllowDamage) + if(m_scene.RegionInfo.RegionSettings.AllowDamage) avatar.Invulnerable = false; else - avatar.Invulnerable = true; + avatar.Invulnerable = (over.LandData.Flags & (uint)ParcelFlags.AllowDamage) == 0; SendLandUpdateToClient(snap_selection, avatar.ControllingClient); avatar.currentParcelUUID = LandData.GlobalID; From 7dbc5803a6321dc13fccb3d7eef31963e2e28278 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Aug 2016 02:49:46 +0100 Subject: [PATCH 30/41] in GetUsersNames(string[] ids) dont loose names HGFriends may have cached --- .../UserManagement/UserManagementModule.cs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 2fd9183198..640ca4eab6 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -488,9 +488,10 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return ret; List missing = new List(); - + Dictionary untried = new Dictionary(); // look in cache UserData userdata = new UserData(); + UUID uuid = UUID.Zero; foreach(string id in ids) { @@ -499,11 +500,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement lock (m_UserCache) { if (m_UserCache.TryGetValue(uuid, out userdata) && - userdata.HasGridUserTried && userdata.FirstName != "Unknown") { string name = userdata.FirstName + " " + userdata.LastName; - ret[uuid] = name; + + if(userdata.HasGridUserTried) + ret[uuid] = name; + else + { + untried[uuid] = name; + missing.Add(id); + } } else missing.Add(id); @@ -527,6 +534,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string name = uac.FirstName + " " + uac.LastName; ret[uac.PrincipalID] = name; missing.Remove(uac.PrincipalID.ToString()); // slowww + untried.Remove(uac.PrincipalID); userdata = new UserData(); userdata.Id = uac.PrincipalID; @@ -567,6 +575,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string name = first.Replace(" ", ".") + "." + last.Replace(" ", ".") + " @" + new Uri(url).Authority; ret[u] = name; missing.Remove(u.ToString()); + untried.Remove(u); } catch { @@ -577,6 +586,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement } } + // add the untried in cache that still failed + if(untried.Count > 0) + { + foreach(KeyValuePair kvp in untried) + { + ret[kvp.Key] = kvp.Value; + missing.Remove(kvp.Key.ToString()); + } + } + // add the UMMthings ( not sure we should) if(missing.Count > 0) { From df8f189f5c152e072e0b1cadc0b8c75ea553f56f Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Wed, 17 Aug 2016 22:44:40 -0400 Subject: [PATCH 31/41] Fixed typo in two group messages --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- .../Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 73fc22ce4e..3144ed0046 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -784,7 +784,7 @@ namespace OpenSim.Groups if (money != null) money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, MoneyTransactionType.GroupCreate); - remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); + remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); // Update the founder with new group information. SendAgentGroupDataUpdate(remoteClient, false); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 112a41f549..ef9bcb19b3 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -896,7 +896,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); - remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); + remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); // Update the founder with new group information. SendAgentGroupDataUpdate(remoteClient, false); From fedc689170b433370dbea2c7248293bc829d1e80 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Aug 2016 04:16:20 +0100 Subject: [PATCH 32/41] in GetUsersNames(string[] ids) why are empty names in cache? ignore them, cache also information found by GridUserService --- .../UserManagement/UserManagementModule.cs | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 640ca4eab6..eabeaf1133 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -489,6 +489,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement List missing = new List(); Dictionary untried = new Dictionary(); + // look in cache UserData userdata = new UserData(); @@ -500,7 +501,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement lock (m_UserCache) { if (m_UserCache.TryGetValue(uuid, out userdata) && - userdata.FirstName != "Unknown") + userdata.FirstName != "Unknown" && userdata.FirstName != string.Empty) { string name = userdata.FirstName + " " + userdata.LastName; @@ -562,20 +563,30 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement if (uInfo != null) { string url, first, last, tmp; - UUID u; + if(uInfo.UserID.Length <= 36) continue; - if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp)) + if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out uuid, out url, out first, out last, out tmp)) { if (url != string.Empty) { try { - string name = first.Replace(" ", ".") + "." + last.Replace(" ", ".") + " @" + new Uri(url).Authority; - ret[u] = name; - missing.Remove(u.ToString()); - untried.Remove(u); + userdata = new UserData(); + userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", "."); + userdata.LastName = "@" + new Uri(url).Authority; + userdata.Id = uuid; + userdata.HomeURL = url; + userdata.IsUnknownUser = false; + userdata.HasGridUserTried = true; + lock (m_UserCache) + m_UserCache[uuid] = userdata; + + string name = userdata.FirstName + " " + userdata.LastName; + ret[uuid] = name; + missing.Remove(uuid.ToString()); + untried.Remove(uuid); } catch { @@ -592,7 +603,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement foreach(KeyValuePair kvp in untried) { ret[kvp.Key] = kvp.Value; - missing.Remove(kvp.Key.ToString()); + missing.Remove((kvp.Key).ToString()); } } From e58e6daf4a388aee1de80ef0ac36b286eb51d1c2 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Aug 2016 07:48:46 +0100 Subject: [PATCH 33/41] several changes on BunchOfCaps. Move some mesh cost initialization to its class it, change caps path to be plain random UUID (except SEED) --- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 184 ++++++------------ .../Caps/BunchOfCaps/BunchOfCapsModule.cs | 2 +- .../Linden/Caps/BunchOfCaps/MeshCost.cs | 21 ++ 3 files changed, 78 insertions(+), 129 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 19619c1e1a..c5164caec0 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -89,23 +89,11 @@ namespace OpenSim.Region.ClientStack.Linden LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_Scene; + private UUID m_AgentID; private Caps m_HostCapsObj; private ModelCost m_ModelCost; - private static readonly string m_requestPath = "0000/"; - // private static readonly string m_mapLayerPath = "0001/"; - private static readonly string m_newInventory = "0002/"; - //private static readonly string m_requestTexture = "0003/"; - private static readonly string m_notecardUpdatePath = "0004/"; - private static readonly string m_notecardTaskUpdatePath = "0005/"; - // private static readonly string m_fetchInventoryPath = "0006/"; - private static readonly string m_copyFromNotecardPath = "0007/"; // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. - private static readonly string m_getObjectPhysicsDataPath = "0101/"; - private static readonly string m_getObjectCostPath = "0102/"; - private static readonly string m_ResourceCostSelectedPath = "0103/"; - private static readonly string m_UpdateAgentInformationPath = "0500/"; - private static readonly string m_animSetTaskUpdatePath = "0260/"; // These are callbacks which will be setup by the scene so that we can update scene data when we // receive capability calls @@ -143,27 +131,16 @@ namespace OpenSim.Region.ClientStack.Linden } private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle; - public BunchOfCaps(Scene scene, Caps caps) + public BunchOfCaps(Scene scene, UUID agentID, Caps caps) { m_Scene = scene; + m_AgentID = agentID; m_HostCapsObj = caps; // create a model upload cost provider - m_ModelCost = new ModelCost(); - // tell it about scene object limits - m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys; - m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys; - m_ModelCost.ObjectLinkedPartsMax = m_Scene.m_linksetCapacity; - -// m_ModelCost.ObjectLinkedPartsMax = ?? -// m_ModelCost.PrimScaleMin = ?? - + m_ModelCost = new ModelCost(scene); + m_PrimScaleMin = m_ModelCost.PrimScaleMin; - float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor; - float modelUploadFactor = m_ModelCost.ModelMeshCostFactor; - float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor; - float modelPrimCreationCost = m_ModelCost.primCreationCost; - float modelMeshByteCost = m_ModelCost.bytecost; IConfigSource config = m_Scene.Config; if (config != null) @@ -183,12 +160,7 @@ namespace OpenSim.Region.ClientStack.Linden IConfig EconomyConfig = config.Configs["Economy"]; if (EconomyConfig != null) { - modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor); - modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor); - modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor); - // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost - modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost); - modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost); + m_ModelCost.Econfig(EconomyConfig); m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory); @@ -203,12 +175,6 @@ namespace OpenSim.Region.ClientStack.Linden if (id != null) m_testAssetsCreatorID = id; } - - m_ModelCost.ModelMeshCostFactor = modelUploadFactor; - m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor; - m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor; - m_ModelCost.primCreationCost = modelPrimCreationCost; - m_ModelCost.bytecost = modelMeshByteCost; } } @@ -225,48 +191,54 @@ namespace OpenSim.Region.ClientStack.Linden m_FileAgentInventoryState = FileAgentInventoryState.idle; } + public string GetNewCapPath() + { + UUID tmpid = UUID.Random(); + return "/CAPS/" + tmpid.ToString(); + } + /// /// Register a bunch of CAPS http service handlers /// public void RegisterHandlers() { - string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; + // this path is also defined elsewhere so keeping it + string seedcapsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath +"0000/"; - RegisterRegionServiceHandlers(capsBase); - RegisterInventoryServiceHandlers(capsBase); + // the root of all evil path needs to be capsBase + m_requestPath + m_HostCapsObj.RegisterHandler( + "SEED", new RestStreamHandler("POST", seedcapsBase, SeedCapRequest, "SEED", null)); + +// m_log.DebugFormat( +// "[CAPS]: Registered seed capability {0} for {1}", seedcapsBase, m_HostCapsObj.AgentID); + + RegisterRegionServiceHandlers(); + RegisterInventoryServiceHandlers(); } - public void RegisterRegionServiceHandlers(string capsBase) + public void RegisterRegionServiceHandlers() { try { - // the root of all evil - m_HostCapsObj.RegisterHandler( - "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); - -// m_log.DebugFormat( -// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); - //m_capsHandlers["MapLayer"] = // new LLSDStreamhandler("POST", - // capsBase + m_mapLayerPath, + // GetNewCapPath(), // GetMapLayer); - IRequestHandler getObjectPhysicsDataHandler - = new RestStreamHandler( - "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null); + IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler( + "POST", GetNewCapPath(), GetObjectPhysicsData, "GetObjectPhysicsData", null); m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler); - IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost); + IRequestHandler getObjectCostHandler = new RestStreamHandler( + "POST", GetNewCapPath(), GetObjectCost, "GetObjectCost", null ); m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler); - IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected); + + IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler( + "POST", GetNewCapPath(), ResourceCostSelected, "ResourceCostSelected", null); m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler); - - - IRequestHandler req - = new RestStreamHandler( - "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null); + IRequestHandler req = new RestStreamHandler( + "POST", GetNewCapPath(), ScriptTaskInventory, "UpdateScript", null); m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); @@ -282,65 +254,29 @@ namespace OpenSim.Region.ClientStack.Linden } } - public void RegisterInventoryServiceHandlers(string capsBase) + public void RegisterInventoryServiceHandlers() { try { - m_HostCapsObj.RegisterHandler( - "NewFileAgentInventory", + m_HostCapsObj.RegisterHandler("NewFileAgentInventory", new LLSDStreamhandler( - "POST", - capsBase + m_newInventory, - NewAgentInventoryRequest, - "NewFileAgentInventory", - null)); - - IRequestHandler req - = new RestStreamHandler( - "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null); + "POST", GetNewCapPath(), NewAgentInventoryRequest, "NewFileAgentInventory", null)); + IRequestHandler req = new RestStreamHandler( + "POST", GetNewCapPath(), NoteCardAgentInventory, "Update*", null); m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); m_HostCapsObj.RegisterHandler("UpdateAnimSetAgentInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); - - - IRequestHandler UpdateAgentInformationHandler - = new RestStreamHandler( - "POST", capsBase + m_UpdateAgentInformationPath, UpdateAgentInformation, "UpdateAgentInformation", null); + IRequestHandler UpdateAgentInformationHandler = new RestStreamHandler( + "POST", GetNewCapPath(), UpdateAgentInformation, "UpdateAgentInformation", null); m_HostCapsObj.RegisterHandler("UpdateAgentInformation", UpdateAgentInformationHandler); - m_HostCapsObj.RegisterHandler( - "CopyInventoryFromNotecard", - new RestStreamHandler( - "POST", capsBase + m_copyFromNotecardPath, CopyInventoryFromNotecard, "CopyInventoryFromNotecard", null)); + IRequestHandler CopyInventoryFromNotecardHandler = new RestStreamHandler( + "POST", GetNewCapPath(), CopyInventoryFromNotecard, "CopyInventoryFromNotecard", null); + m_HostCapsObj.RegisterHandler("CopyInventoryFromNotecard", CopyInventoryFromNotecardHandler); - // As of RC 1.22.9 of the Linden client this is - // supported - - //m_capsHandlers["WebFetchInventoryDescendents"] =new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryDescendentsRequest); - - // justincc: I've disabled the CAPS service for now to fix problems with selecting textures, and - // subsequent inventory breakage, in the edit object pane (such as mantis 1085). This requires - // enhancements (probably filling out the folder part of the LLSD reply) to our CAPS service, - // but when I went on the Linden grid, the - // simulators I visited (version 1.21) were, surprisingly, no longer supplying this capability. Instead, - // the 1.19.1.4 client appeared to be happily flowing inventory data over UDP - // - // This is very probably just a temporary measure - once the CAPS service appears again on the Linden grid - // we will be - // able to get the data we need to implement the necessary part of the protocol to fix the issue above. - // m_capsHandlers["FetchInventoryDescendents"] = - // new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryRequest); - - // m_capsHandlers["FetchInventoryDescendents"] = - // new LLSDStreamhandler("POST", - // capsBase + m_fetchInventory, - // FetchInventory)); - // m_capsHandlers["RequestTextureDownload"] = new RestStreamHandler("POST", - // capsBase + m_requestTexture, - // RequestTexture); } catch (Exception e) { @@ -409,30 +345,28 @@ namespace OpenSim.Region.ClientStack.Linden LLSDTaskScriptUpdate llsdUpdateRequest = new LLSDTaskScriptUpdate(); LLSDHelpers.DeserialiseOSDMap(hash, llsdUpdateRequest); - string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; - string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + string uploaderPath = GetNewCapPath(); TaskInventoryScriptUpdater uploader = new TaskInventoryScriptUpdater( llsdUpdateRequest.item_id, llsdUpdateRequest.task_id, llsdUpdateRequest.is_script_running, - capsBase + uploaderPath, + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); uploader.OnUpLoad += TaskScriptUpdated; m_HostCapsObj.HttpListener.AddStreamHandler( new BinaryStreamHandler( - "POST", capsBase + uploaderPath, uploader.uploaderCaps, "TaskInventoryScriptUpdater", null)); + "POST", uploaderPath, uploader.uploaderCaps, "TaskInventoryScriptUpdater", null)); string protocol = "http://"; if (m_HostCapsObj.SSLCaps) protocol = "https://"; - string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + - uploaderPath; + string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + uploaderPath; LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); uploadResponse.uploader = uploaderURL; @@ -653,11 +587,10 @@ namespace OpenSim.Region.ClientStack.Linden } string assetDes = llsdRequest.description; - string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; UUID newAsset = UUID.Random(); UUID newInvItem = UUID.Random(); UUID parentFolder = llsdRequest.folder_id; - string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + string uploaderPath = GetNewCapPath(); UUID texturesFolder = UUID.Zero; if(!IsAtestUpload && m_enableModelUploadTextureToInventory) @@ -665,26 +598,23 @@ namespace OpenSim.Region.ClientStack.Linden AssetUploader uploader = new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, - llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost, + llsdRequest.asset_type, uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost, texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload, llsdRequest.next_owner_mask, llsdRequest.group_mask, llsdRequest.everyone_mask); m_HostCapsObj.HttpListener.AddStreamHandler( new BinaryStreamHandler( "POST", - capsBase + uploaderPath, + uploaderPath, uploader.uploaderCaps, "NewAgentInventoryRequest", m_HostCapsObj.AgentID.ToString())); string protocol = "http://"; - if (m_HostCapsObj.SSLCaps) protocol = "https://"; - string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + - uploaderPath; - + string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + uploaderPath; LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); uploadResponse.uploader = uploaderURL; @@ -1313,24 +1243,22 @@ namespace OpenSim.Region.ClientStack.Linden LLSDItemUpdate llsdRequest = new LLSDItemUpdate(); LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest); - string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; - string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + string uploaderPath = GetNewCapPath(); ItemUpdater uploader = - new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); + new ItemUpdater(llsdRequest.item_id, uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); uploader.OnUpLoad += ItemUpdated; m_HostCapsObj.HttpListener.AddStreamHandler( new BinaryStreamHandler( - "POST", capsBase + uploaderPath, uploader.uploaderCaps, "NoteCardAgentInventory", null)); + "POST", uploaderPath, uploader.uploaderCaps, "NoteCardAgentInventory", null)); string protocol = "http://"; if (m_HostCapsObj.SSLCaps) protocol = "https://"; - string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + - uploaderPath; + string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + uploaderPath; LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); uploadResponse.uploader = uploaderURL; diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs index c241075b52..5b4e0da88c 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs @@ -84,7 +84,7 @@ namespace OpenSim.Region.ClientStack.Linden private void OnRegisterCaps(UUID agentID, Caps caps) { - new BunchOfCaps(m_Scene, caps); + new BunchOfCaps(m_Scene, agentID, caps); } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs index 29bde6c063..fb22694bd2 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs @@ -45,6 +45,8 @@ using ComponentAce.Compression.Libs.zlib; using OSDArray = OpenMetaverse.StructuredData.OSDArray; using OSDMap = OpenMetaverse.StructuredData.OSDMap; +using Nini.Config; + namespace OpenSim.Region.ClientStack.Linden { public struct ModelPrimLimits @@ -100,6 +102,25 @@ namespace OpenSim.Region.ClientStack.Linden public float PhysicalPrimScaleMax = 10f; public int ObjectLinkedPartsMax = 512; + + public ModelCost(Scene scene) + { + PrimScaleMin = scene.m_minNonphys; + NonPhysicalPrimScaleMax = scene.m_maxNonphys; + PhysicalPrimScaleMax = scene.m_maxPhys; + ObjectLinkedPartsMax = scene.m_linksetCapacity; + } + + public void Econfig(IConfig EconomyConfig) + { + ModelMeshCostFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", ModelMeshCostFactor); + ModelTextureCostFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", ModelTextureCostFactor); + ModelMinCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", ModelMinCostFactor); + // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost + primCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", primCreationCost); + bytecost = EconomyConfig.GetFloat("ModelMeshByteCost", bytecost); + } + // storage for a single mesh asset cost parameters private class ameshCostParam { From ac542715f1712eaba298a0a8e42c3ce9b0c7f24a Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Aug 2016 12:45:11 +0100 Subject: [PATCH 34/41] add caps HomeLocation ; add client SendAlertMessage(string message, string info), where info in info message field. only minimal testing done --- OpenSim/Framework/IClientAPI.cs | 4 +- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 145 +++++++++++++++++- .../ClientStack/Linden/UDP/LLClientView.cs | 12 ++ .../Server/IRCClientView.cs | 5 + .../OptionalModules/World/NPC/NPCAvatar.cs | 4 + OpenSim/Tests/Common/Mock/TestClient.cs | 4 + 6 files changed, 171 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 848d574fe3..c046010a3c 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1256,9 +1256,11 @@ namespace OpenSim.Framework void SendAttachedSoundGainChange(UUID objectID, float gain); void SendNameReply(UUID profileId, string firstname, string lastname); - void SendAlertMessage(string message); + void SendAlertMessage(string message); + void SendAlertMessage(string message, string into); void SendAgentAlertMessage(string message, bool modal); + void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, string url); /// diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index c5164caec0..bedd3d09ce 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -193,8 +193,7 @@ namespace OpenSim.Region.ClientStack.Linden public string GetNewCapPath() { - UUID tmpid = UUID.Random(); - return "/CAPS/" + tmpid.ToString(); + return "/CAPS/" + UUID.Random(); } /// @@ -242,6 +241,10 @@ namespace OpenSim.Region.ClientStack.Linden m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); + IRequestHandler HomeLocationHandler = new RestStreamHandler( + "POST", GetNewCapPath(), HomeLocation, "HomeLocation", null); + m_HostCapsObj.RegisterHandler("HomeLocation", HomeLocationHandler); + // IRequestHandler animSetRequestHandler // = new RestStreamHandler( // "POST", capsBase + m_animSetTaskUpdatePath, AnimSetTaskInventory, "UpdateScript", null); @@ -1504,6 +1507,144 @@ namespace OpenSim.Region.ClientStack.Linden string response = OSDParser.SerializeLLSDXmlString(resp); return response; } + + public bool OSDMapTOVector3(OSDMap map, out Vector3 v) + { + v = Vector3.Zero; + if(!map.ContainsKey("X")) + return false; + if(!map.ContainsKey("Y")) + return false; + if(!map.ContainsKey("Z")) + return false; + v.X = (float)map["X"].AsReal(); + v.Y = (float)map["Y"].AsReal(); + v.Z = (float)map["Z"].AsReal(); + return true; + } + + public string HomeLocation(string request, string path, string param, IOSHttpRequest httpRequest, + IOSHttpResponse httpResponse) + { + OSDMap resp = new OSDMap(); + + resp["success"] = "false"; + + + bool fail = true; + string message = "Set Home request failed"; + int locationID = 1; + Vector3 pos = Vector3.Zero; + Vector3 lookAt = Vector3.Zero; + + IClientAPI client = null; + ScenePresence sp; + + while(true) + { + if(m_Scene.GridUserService == null) + break; + + if(m_Scene.UserManagementModule == null) + break; + + m_Scene.TryGetScenePresence(m_AgentID, out sp); + if(sp == null || sp.IsChildAgent || sp.IsDeleted || sp.IsInTransit) + break; + + client = sp.ControllingClient; + + if(!m_Scene.UserManagementModule.IsLocalGridUser(m_AgentID)) + break; + + OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); + if(!req.ContainsKey("HomeLocation")) + break; + + OSDMap HLocation = (OSDMap)req["HomeLocation"]; + if(!HLocation.ContainsKey("LocationPos")) + break; + if(!HLocation.ContainsKey("LocationLookAt")) + break; + + locationID = HLocation["LocationId"].AsInteger(); + + if(!OSDMapTOVector3((OSDMap)HLocation["LocationPos"], out pos)) + break; + + if(!OSDMapTOVector3((OSDMap)HLocation["LocationLookAt"], out lookAt)) + break; + + ILandObject land = m_Scene.LandChannel.GetLandObject(pos); + if(land == null) + break; + + ulong gpowers = client.GetGroupPowers(land.LandData.GroupID); + SceneObjectGroup telehub = null; + if (m_Scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero) + // Does the telehub exist in the scene? + telehub = m_Scene.GetSceneObjectGroup(m_Scene.RegionInfo.RegionSettings.TelehubObject); + + if (!m_Scene.Permissions.IsAdministrator(m_AgentID) && // (a) gods and land managers can set home + !m_Scene.Permissions.IsGod(m_AgentID) && + m_AgentID != land.LandData.OwnerID && // (b) land owners can set home + // (c) members of the land-associated group in roles that can set home + ((gpowers & (ulong)GroupPowers.AllowSetHome) != (ulong)GroupPowers.AllowSetHome) && + // (d) parcels with telehubs can be the home of anyone + (telehub == null || !land.ContainsPoint((int)telehub.AbsolutePosition.X, (int)telehub.AbsolutePosition.Y))) + { + message = "You are not allowed to set your home location in this parcel."; + break; + } + + string userId; + UUID test; + if (!m_Scene.UserManagementModule.GetUserUUI(m_AgentID, out userId)) + { + message = "Set Home request failed. (User Lookup)"; + break; + } + + if (!UUID.TryParse(userId, out test)) + { + message = "Set Home request failed. (HG visitor)"; + break; + } + + if (m_Scene.GridUserService.SetHome(userId, land.RegionUUID, pos, lookAt)) + fail = false; + + break; + } + + string response; + + if(fail) + { + if(client != null) + client.SendAlertMessage(message, "HomePositionSet"); + response = OSDParser.SerializeLLSDXmlString(resp); + return response; + } + + // so its http but still needs a udp reply to inform user? crap :p + if(client != null) + client.SendAlertMessage("Home position set.","HomePositionSet"); + + resp["success"] = "true"; + OSDMap homeloc = new OSDMap(); + OSDMap homelocpos = new OSDMap(); + // for some odd reason viewers send pos as reals but read as integer + homelocpos["X"] = new OSDReal(pos.X); + homelocpos["Y"] = new OSDReal(pos.Y); + homelocpos["Z"] = new OSDReal(pos.Z); + homeloc["LocationPos"] = homelocpos; + + resp["HomeLocation"] = homeloc; + + response = OSDParser.SerializeLLSDXmlString(resp); + return response; + } } public class AssetUploader diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6275f19199..f580e5a641 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2411,6 +2411,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(alertPack, ThrottleOutPacketType.Task); } + public void SendAlertMessage(string message, string info) + { + AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage); + alertPack.AlertData = new AlertMessagePacket.AlertDataBlock(); + alertPack.AlertData.Message = Util.StringToBytes256(message); + alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[1]; + alertPack.AlertInfo[0] = new AlertMessagePacket.AlertInfoBlock(); + alertPack.AlertInfo[0].Message = Util.StringToBytes256(info); + alertPack.AlertInfo[0].ExtraParams = new Byte[0]; + OutPacket(alertPack, ThrottleOutPacketType.Task); + } + /// /// Send an agent alert message to the client. /// diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 50be3aced7..e21d69fdb0 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1217,6 +1217,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } + public void SendAlertMessage(string message, string info) + { + + } + public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, string url) { IRC_SendChannelPrivmsg(objectname,url); diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 4275192a33..52e86609b8 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -885,6 +885,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } + public void SendAlertMessage(string message, string info) + { + } + public void SendSystemAlertMessage(string message) { } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 4f8e986771..9b087c9be0 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -861,6 +861,10 @@ namespace OpenSim.Tests.Common { } + public void SendAlertMessage(string message, string info) + { + } + public void SendSystemAlertMessage(string message) { } From 4b73550eeeafa52e23c326c9b2e87ac4e9624b7b Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Aug 2016 13:17:36 +0100 Subject: [PATCH 35/41] allow cap HomeLocation to be disabled setting Cap_HomeLocation = "" --- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 19 ++++++++++++++++--- bin/OpenSimDefaults.ini | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index bedd3d09ce..f5b46bd20c 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -122,6 +122,8 @@ namespace OpenSim.Region.ClientStack.Linden private float m_PrimScaleMin = 0.001f; + private bool m_AllowCapHomeLocation = true; + private enum FileAgentInventoryState : int { idle = 0, @@ -176,6 +178,15 @@ namespace OpenSim.Region.ClientStack.Linden m_testAssetsCreatorID = id; } } + + IConfig CapsConfig = config.Configs["ClientStack.LindenCaps"]; + if (CapsConfig != null) + { + string homeLocationUrl = CapsConfig.GetString("Cap_HomeLocation", "localhost"); + if(homeLocationUrl == String.Empty) + m_AllowCapHomeLocation = false; + + } } m_assetService = m_Scene.AssetService; @@ -241,10 +252,12 @@ namespace OpenSim.Region.ClientStack.Linden m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); - IRequestHandler HomeLocationHandler = new RestStreamHandler( + if(m_AllowCapHomeLocation) + { + IRequestHandler HomeLocationHandler = new RestStreamHandler( "POST", GetNewCapPath(), HomeLocation, "HomeLocation", null); - m_HostCapsObj.RegisterHandler("HomeLocation", HomeLocationHandler); - + m_HostCapsObj.RegisterHandler("HomeLocation", HomeLocationHandler); + } // IRequestHandler animSetRequestHandler // = new RestStreamHandler( // "POST", capsBase + m_animSetTaskUpdatePath, AnimSetTaskInventory, "UpdateScript", null); diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index df92921a00..dbc09fd89c 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -725,7 +725,7 @@ Cap_GetObjectCost = "" Cap_GetObjectPhysicsData = "" Cap_GroupProposalBallot = "" - Cap_HomeLocation = "" + Cap_HomeLocation = "localhost" Cap_LandResources = "" Cap_MapLayer = "localhost" Cap_MapLayerGod = "localhost" From 9c75f8a57e205cc33b0cbf97745ab7ead46da399 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Aug 2016 14:35:28 +0100 Subject: [PATCH 36/41] avoid NULL refs --- OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs | 2 ++ .../Handlers/UserAccounts/UserAccountServerPostHandler.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs index b63b59481d..8806c2cbbd 100644 --- a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs +++ b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs @@ -228,6 +228,8 @@ namespace OpenSim.Server.Handlers.GridUser int i = 0; foreach (GridUserInfo pinfo in pinfos) { + if(pinfo == null) + continue; Dictionary rinfoDict = pinfo.ToKeyValuePairs(); result["griduser" + i] = rinfoDict; i++; diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs index 9efe741b94..237ffc7ee3 100644 --- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs +++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs @@ -235,6 +235,8 @@ namespace OpenSim.Server.Handlers.UserAccounts int i = 0; foreach (UserAccount acc in accounts) { + if(acc == null) + continue; Dictionary rinfoDict = acc.ToKeyValuePairs(); result["account" + i] = rinfoDict; i++; From 847d351bf5efc466d028ee3c65a643b89d3a60ca Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Thu, 18 Aug 2016 14:50:50 -0400 Subject: [PATCH 37/41] Fixed grammer in a comment --- OpenSim/Addons/Groups/GroupsModule.cs | 2 +- .../Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 3144ed0046..57fbbf7893 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -764,7 +764,7 @@ namespace OpenSim.Groups } // check funds - // is there is a money module present ? + // is there a money module present ? IMoneyModule money = scene.RequestModuleInterface(); if (money != null) { diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index ef9bcb19b3..7663a392b6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -883,7 +883,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // check funds - // is there is a money module present ? + // is there a money module present ? IMoneyModule money = scene.RequestModuleInterface(); if (money != null) { From 1b2e240bf8ba087827e05229554958eec3f7c9e7 Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Thu, 18 Aug 2016 15:01:35 -0400 Subject: [PATCH 38/41] Collect any group join fees. Pass group name when applying join/create fees. --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 7663a392b6..626937c70d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -862,7 +862,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name) != null) + GroupRecord groupRecord = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name); + + if (groupRecord != null) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists."); return UUID.Zero; @@ -877,7 +879,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (avatar.UserLevel < m_levelGroupCreate) { - remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient permissions to create a group."); + remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have insufficient permissions to create a group."); return UUID.Zero; } } @@ -885,14 +887,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // check funds // is there a money module present ? IMoneyModule money = scene.RequestModuleInterface(); - if (money != null) + if (money != null && money.GroupCreationCharge > 0) { - // do the transaction, that is if the agent has got sufficient funds + // do the transaction, that is if the agent has sufficient funds if (!money.AmountCovered(remoteClient.AgentId, money.GroupCreationCharge)) { - remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group."); + remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have insufficient funds to create a group."); return UUID.Zero; } - money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate); + money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate, name); } UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); @@ -1092,6 +1094,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Should check to see if OpenEnrollment, or if there's an outstanding invitation m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, UUID.Zero); + // check funds + // is there a money module present ? + GroupRecord groupRecord = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); + IMoneyModule money = remoteClient.Scene.RequestModuleInterface(); + if (money != null && groupRecord.MembershipFee > 0) + { + // do the transaction, that is if the agent has sufficient funds + if (!money.AmountCovered(GetRequestingAgentID(remoteClient), groupRecord.MembershipFee)) { + remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have insufficient funds to join the group."); + return; + } + money.ApplyCharge(GetRequestingAgentID(remoteClient), groupRecord.MembershipFee, MoneyTransactionType.GroupJoin, groupRecord.GroupName); + } + remoteClient.SendJoinGroupReply(groupID, true); SendAgentGroupDataUpdate(remoteClient, true); From c53d74274d1fa9e76621206185ee4e1ff3c57f16 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 19 Aug 2016 00:14:46 +0100 Subject: [PATCH 39/41] missed another UserAccounts cache, add a few locks --- .../LocalUserAccountServiceConnector.cs | 51 ++++++++++++++++--- .../RemoteUserAccountServiceConnector.cs | 31 ++++++++--- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs index 1bb470477c..3127199586 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs @@ -153,12 +153,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public UserAccount GetUserAccount(UUID scopeID, UUID userID) { bool inCache = false; - UserAccount account = m_Cache.Get(userID, out inCache); + UserAccount account; + lock(m_Cache) + account = m_Cache.Get(userID, out inCache); if (inCache) return account; account = UserAccountService.GetUserAccount(scopeID, userID); - m_Cache.Cache(userID, account); + lock(m_Cache) + m_Cache.Cache(userID, account); return account; } @@ -166,13 +169,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) { bool inCache = false; - UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache); + UserAccount account; + lock(m_Cache) + account = m_Cache.Get(firstName + " " + lastName, out inCache); if (inCache) return account; account = UserAccountService.GetUserAccount(scopeID, firstName, lastName); if (account != null) - m_Cache.Cache(account.PrincipalID, account); + lock(m_Cache) + m_Cache.Cache(account.PrincipalID, account); return account; } @@ -184,9 +190,42 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public List GetUserAccounts(UUID scopeID, List IDs) { - return UserAccountService.GetUserAccounts(scopeID, IDs); - } + List ret = new List(); + List missing = new List(); + // still another cache.. + bool inCache = false; + UUID uuid = UUID.Zero; + UserAccount account; + foreach(string id in IDs) + { + if(UUID.TryParse(id, out uuid)) + { + lock(m_Cache) + account = m_Cache.Get(uuid, out inCache); + if (inCache) + ret.Add(account); + else + missing.Add(id); + } + } + + if(missing.Count == 0) + return ret; + + List ext = UserAccountService.GetUserAccounts(scopeID, missing); + if(ext != null && ext.Count > 0) + { + ret.AddRange(ext); + foreach(UserAccount acc in ext) + { + if(acc != null) + lock(m_Cache) + m_Cache.Cache(acc.PrincipalID, acc); + } + } + return ret; + } public List GetUserAccountsWhere(UUID scopeID, string query) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs index 90c90d6f1b..eead05d7ae 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs @@ -128,7 +128,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts // flags, title, etc. And country, don't forget country! private void OnNewClient(IClientAPI client) { - m_Cache.Remove(client.Name); + lock(m_Cache) + m_Cache.Remove(client.Name); } #region Overwritten methods from IUserAccountService @@ -136,12 +137,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public override UserAccount GetUserAccount(UUID scopeID, UUID userID) { bool inCache = false; - UserAccount account = m_Cache.Get(userID, out inCache); + UserAccount account; + lock(m_Cache) + account = m_Cache.Get(userID, out inCache); if (inCache) return account; account = base.GetUserAccount(scopeID, userID); - m_Cache.Cache(userID, account); + lock(m_Cache) + if(account != null) + m_Cache.Cache(userID, account); return account; } @@ -149,13 +154,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public override UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) { bool inCache = false; - UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache); + UserAccount account; + lock(m_Cache) + account = m_Cache.Get(firstName + " " + lastName, out inCache); if (inCache) return account; account = base.GetUserAccount(scopeID, firstName, lastName); if (account != null) - m_Cache.Cache(account.PrincipalID, account); + lock(m_Cache) + m_Cache.Cache(account.PrincipalID, account); return account; } @@ -173,7 +181,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts { if(UUID.TryParse(id, out uuid)) { - account = m_Cache.Get(uuid, out inCache); + lock(m_Cache) + account = m_Cache.Get(uuid, out inCache); if (inCache) accs.Add(account); else @@ -184,8 +193,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts if(missing.Count > 0) { List ext = base.GetUserAccounts(scopeID, missing); - if(ext != null) + if(ext != null && ext.Count >0 ) + { accs.AddRange(ext); + foreach(UserAccount acc in ext) + { + if(acc != null) + lock(m_Cache) + m_Cache.Cache(acc.PrincipalID, acc); + } + } } return accs; From d701de402101f8ecc4a1892bb2d7cf296bd9b990 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 19 Aug 2016 02:26:49 +0100 Subject: [PATCH 40/41] add cap GroupMemberData --- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 133 +++++++++++++++++- bin/OpenSimDefaults.ini | 1 + 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index f5b46bd20c..c3305cfb0a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -41,6 +41,7 @@ using log4net; using OpenSim.Framework; using OpenSim.Framework.Capabilities; using OpenSim.Region.Framework; +using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Framework.Servers; @@ -123,6 +124,7 @@ namespace OpenSim.Region.ClientStack.Linden private float m_PrimScaleMin = 0.001f; private bool m_AllowCapHomeLocation = true; + private bool m_AllowCapGroupMemberData = true; private enum FileAgentInventoryState : int { @@ -185,7 +187,10 @@ namespace OpenSim.Region.ClientStack.Linden string homeLocationUrl = CapsConfig.GetString("Cap_HomeLocation", "localhost"); if(homeLocationUrl == String.Empty) m_AllowCapHomeLocation = false; - + + string GroupMemberDataUrl = CapsConfig.GetString("Cap_GroupMemberData", "localhost"); + if(GroupMemberDataUrl == String.Empty) + m_AllowCapGroupMemberData = false; } } @@ -258,6 +263,15 @@ namespace OpenSim.Region.ClientStack.Linden "POST", GetNewCapPath(), HomeLocation, "HomeLocation", null); m_HostCapsObj.RegisterHandler("HomeLocation", HomeLocationHandler); } + + if(m_AllowCapGroupMemberData) + { + IRequestHandler GroupMemberDataHandler = new RestStreamHandler( + "POST", GetNewCapPath(), GroupMemberData, "GroupMemberData", null); + m_HostCapsObj.RegisterHandler("GroupMemberData", GroupMemberDataHandler); + } + + // IRequestHandler animSetRequestHandler // = new RestStreamHandler( // "POST", capsBase + m_animSetTaskUpdatePath, AnimSetTaskInventory, "UpdateScript", null); @@ -1658,6 +1672,123 @@ namespace OpenSim.Region.ClientStack.Linden response = OSDParser.SerializeLLSDXmlString(resp); return response; } + + private static int CompareRolesByMembersDesc(GroupRolesData x, GroupRolesData y) + { + return -(x.Members.CompareTo(y.Members)); + } + + public string GroupMemberData(string request, string path, string param, IOSHttpRequest httpRequest, + IOSHttpResponse httpResponse) + { + OSDMap resp = new OSDMap(); + + string response; + + bool fail = true; + IClientAPI client = null; + ScenePresence sp; + IGroupsModule m_GroupsModule; + UUID groupID = UUID.Zero; + + while(true) + { + m_GroupsModule = m_Scene.RequestModuleInterface(); + if(m_GroupsModule == null) + break; + + m_Scene.TryGetScenePresence(m_AgentID, out sp); + if(sp == null || sp.IsChildAgent || sp.IsDeleted || sp.IsInTransit) + break; + + client = sp.ControllingClient; + + OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); + if(!req.ContainsKey("group_id")) + break; + + groupID = req["group_id"].AsUUID(); + if(groupID == UUID.Zero) + break; + + List roles = m_GroupsModule.GroupRoleDataRequest(client, groupID); + if(roles == null || roles.Count == 0) + break; + + List members = m_GroupsModule.GroupMembersRequest(client, groupID); + if(members == null || members.Count == 0) + break; + + int memberCount = members.Count; + + Dictionary titles = new Dictionary(); + int i = 0; + + ulong defaultPowers = 0; + + + // build titles array and index + roles.Sort(CompareRolesByMembersDesc); + + OSDArray osdtitles = new OSDArray(); + foreach(GroupRolesData grd in roles) + { + string title = grd.Title; + if(i==0) + defaultPowers = grd.Powers; + + if(!titles.ContainsKey(title)) + { + titles[title] = i++; + osdtitles.Add(new OSDString(title)); + } + } + + OSDMap osdmembers = new OSDMap(); + foreach(GroupMembersData gmd in members) + { + OSDMap m = new OSDMap(); + if(gmd.OnlineStatus != null && gmd.OnlineStatus != "") + m["last_login"] = new OSDString(gmd.OnlineStatus); + if(gmd.AgentPowers != defaultPowers) + m["powers"] = new OSDString((gmd.AgentPowers).ToString("X")); + if(titles.ContainsKey(gmd.Title) && titles[gmd.Title] != 0) + m["title"] = new OSDInteger(titles[gmd.Title]); + if(gmd.IsOwner) + m["owner"] = new OSDString("true"); + if(gmd.Contribution != 0) + m["donated_square_meters"] = new OSDInteger(gmd.Contribution); + + osdmembers[(gmd.AgentID).ToString()] = m; + } + + OSDMap osddefaults = new OSDMap(); + osddefaults["default_powers"] = new OSDString(defaultPowers.ToString("X")); + + resp["group_id"] = new OSDUUID(groupID); + resp["agent_id"] = new OSDUUID(m_AgentID); + resp["member_count"] = new OSDInteger(memberCount); + resp["defaults"] = osddefaults; + resp["titles"] = osdtitles; + resp["members"] = osdmembers; + + fail = false; + break; + } + + if(fail) + { + resp["group_id"] = new OSDUUID(groupID); + resp["agent_id"] = new OSDUUID(m_AgentID); + resp["member_count"] = new OSDInteger(0); + resp["defaults"] = new OSDMap(); + resp["titles"] = new OSDArray(); + resp["members"] = new OSDMap(); + } + + response = OSDParser.SerializeLLSDXmlString(resp); + return response; + } } public class AssetUploader diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index dbc09fd89c..6ccea99260 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -725,6 +725,7 @@ Cap_GetObjectCost = "" Cap_GetObjectPhysicsData = "" Cap_GroupProposalBallot = "" + Cap_GroupMemberData = "localhost" Cap_HomeLocation = "localhost" Cap_LandResources = "" Cap_MapLayer = "localhost" From e62d38a4abe3d940ef4dedb6c30681a8d58cdf47 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 19 Aug 2016 02:41:15 +0100 Subject: [PATCH 41/41] catch some NULL refs --- .../ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index c3305cfb0a..60bfaa518b 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -1733,6 +1733,8 @@ namespace OpenSim.Region.ClientStack.Linden OSDArray osdtitles = new OSDArray(); foreach(GroupRolesData grd in roles) { + if(grd.Title == null) + continue; string title = grd.Title; if(i==0) defaultPowers = grd.Powers; @@ -1744,6 +1746,9 @@ namespace OpenSim.Region.ClientStack.Linden } } + if(titles.Count == 0) + break; + OSDMap osdmembers = new OSDMap(); foreach(GroupMembersData gmd in members) { @@ -1752,7 +1757,7 @@ namespace OpenSim.Region.ClientStack.Linden m["last_login"] = new OSDString(gmd.OnlineStatus); if(gmd.AgentPowers != defaultPowers) m["powers"] = new OSDString((gmd.AgentPowers).ToString("X")); - if(titles.ContainsKey(gmd.Title) && titles[gmd.Title] != 0) + if(gmd.Title != null && titles.ContainsKey(gmd.Title) && titles[gmd.Title] != 0) m["title"] = new OSDInteger(titles[gmd.Title]); if(gmd.IsOwner) m["owner"] = new OSDString("true");