diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs index 08c2b38a01..c1030ae313 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs @@ -164,7 +164,6 @@ namespace OpenSim.Region.ClientStack.Linden m_features["BakesOnMeshEnabled"] = true; m_features["PhysicsMaterialsEnabled"] = true; - OSDMap typesMap = new OSDMap(); typesMap["convex"] = true; typesMap["none"] = true; @@ -175,10 +174,14 @@ namespace OpenSim.Region.ClientStack.Linden m_features["LSLSyntaxId"] = OSD.FromUUID(m_scriptSyntaxID); OSDMap meshAnim = new OSDMap(); - meshAnim["AnimatedObjectMaxTris"] = OSD.FromInteger(10000); + meshAnim["AnimatedObjectMaxTris"] = OSD.FromInteger(150000); meshAnim["MaxAgentAnimatedObjectAttachments"] = OSD.FromInteger(2); m_features["AnimatedObjects"] = meshAnim; + m_features["MaxAgentAttachments"] = OSD.FromInteger(Constants.MaxAgentAttachments); + m_features["MaxAgentGroupsBasic"] = OSD.FromInteger(Constants.MaxAgentGroups); + m_features["MaxAgentGroupsPremium"] = OSD.FromInteger(Constants.MaxAgentGroups); + // Extra information for viewers that want to use it // TODO: Take these out of here into their respective modules, like map-server-url OSDMap extrasMap; diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index e342897372..e82dc7f2f0 100755 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -59,6 +59,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments private Scene m_scene; private IRegionConsole m_regionConsole; private IInventoryAccessModule m_invAccessModule; + private bool m_wearReplacesAllOption = true; /// /// Are attachments enabled? @@ -74,6 +75,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (config != null) { Enabled = config.GetBoolean("Enabled", true); + m_wearReplacesAllOption = config.GetBoolean("WearReplacesAll", true); } else { @@ -101,10 +103,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void RemoveRegion(Scene scene) { - m_scene.UnregisterModuleInterface(this); + if (!Enabled) + return; - if (Enabled) - m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; + m_scene.UnregisterModuleInterface(this); + m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; } public void RegionLoaded(Scene scene) @@ -225,8 +228,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ConsoleDisplayList ct = new ConsoleDisplayList(); List attachmentObjects = sp.GetAttachments(); - foreach (SceneObjectGroup attachmentObject in attachmentObjects) + for (int i = 0; i < attachmentObjects.Count; ++i) { + SceneObjectGroup attachmentObject = attachmentObjects[i]; ct.Indent = 2; ct.AddRow("Attachment Name", attachmentObject.Name); ct.AddRow("Local ID", attachmentObject.LocalId); @@ -308,13 +312,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments List attachments = sp.GetAttachments(); if (attachments.Count > 0) { - ad.AttachmentObjects = new List(); - ad.AttachmentObjectStates = new List(); - // IScriptModule se = m_scene.RequestModuleInterface(); + ad.AttachmentObjects = new List(attachments.Count); + ad.AttachmentObjectStates = new List(attachments.Count); sp.InTransitScriptStates.Clear(); - foreach (SceneObjectGroup sog in attachments) + for (int indx = 0; indx < attachments.Count; ++indx) { + SceneObjectGroup sog = attachments[indx]; // We need to make a copy and pass that copy // because of transfers withn the same sim ISceneObject clone = sog.CloneForNewScene(); @@ -343,17 +347,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments sp.ClearAttachments(); int i = 0; - foreach (ISceneObject so in ad.AttachmentObjects) + for (int indx = 0; indx < ad.AttachmentObjects.Count; ++indx) { - ((SceneObjectGroup)so).LocalId = 0; - ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); + SceneObjectGroup sog = (SceneObjectGroup)ad.AttachmentObjects[indx]; + sog.LocalId = 0; + sog.RootPart.ClearUpdateSchedule(); // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", -// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name); +// ad.AttachmentObjectStates[i].Length, sog.Name, sp.Name, m_scene.Name); - so.SetState(ad.AttachmentObjectStates[i++], m_scene); - m_scene.IncomingCreateObject(Vector3.Zero, so); + sog.SetState(ad.AttachmentObjectStates[i++], m_scene); + m_scene.IncomingCreateObject(Vector3.Zero, sog); } } } @@ -363,14 +368,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (!Enabled) return; - if (null == sp.Appearance) + if (sp.Appearance == null) { m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID); - return; } - if (sp.GetAttachments().Count > 0) + if (sp.GetAttachmentsCount() > 0) { if (DebugLevel > 0) m_log.DebugFormat( @@ -420,27 +424,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Let's get all items at once, so they get cached UUID[] items = new UUID[attachments.Count]; - int i = 0; - foreach (AvatarAttachment attach in attachments) - items[i++] = attach.ItemID; + for (int i = 0; i < attachments.Count; ++i) + items[i] = attachments[i].ItemID; + m_scene.InventoryService.GetMultipleItems(sp.UUID, items); - foreach (AvatarAttachment attach in attachments) + for (int indx = 0; indx < attachments.Count; ++indx) { + AvatarAttachment attach = attachments[indx]; uint attachmentPt = (uint)attach.AttachPoint; // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", // attach.ItemID, attach.AssetID, p, sp.Name, m_scene.RegionInfo.RegionName); - // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down - // But they're not used anyway, the item is being looked up for now, so let's proceed. - //if (UUID.Zero == assetID) - //{ - // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); - // continue; - //} - try { string xmlData; @@ -482,24 +479,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (attachments.Count <= 0) return; - Dictionary scriptStates = new Dictionary(); - if (sp.PresenceType != PresenceType.Npc) { - foreach (SceneObjectGroup so in attachments) - { - // Scripts MUST be snapshotted before the object is - // removed from the scene because doing otherwise will - // clobber the run flag - // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from - // scripts performing attachment operations at the same time. Getting object states stops the scripts. - scriptStates[so] = PrepareScriptInstanceForSave(so, false); - } - lock (sp.AttachmentsSyncLock) { - foreach (SceneObjectGroup so in attachments) - UpdateDetachedObject(sp, so, scriptStates[so]); + for (int i = 0; i < attachments.Count; ++i) + { + SceneObjectGroup sog = attachments[i]; + UpdateDetachedObject(sp, sog, PrepareScriptInstanceForSave(sog, false)); + } sp.ClearAttachments(); } } @@ -507,8 +495,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { lock (sp.AttachmentsSyncLock) { - foreach (SceneObjectGroup so in attachments) - UpdateDetachedObject(sp, so, String.Empty); + for (int i = 0; i < attachments.Count; ++i) + UpdateDetachedObject(sp, attachments[i], String.Empty); sp.ClearAttachments(); } } @@ -524,9 +512,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", m_scene.RegionInfo.RegionName, sp.Name, silent); - foreach (SceneObjectGroup sop in sp.GetAttachments()) + List attachments = sp.GetAttachments(); + + for(int i = 0; i < attachments.Count; ++i) { - sop.Scene.DeleteSceneObject(sop, silent); + SceneObjectGroup sog = attachments[i]; + sog.Scene.DeleteSceneObject(sog, silent); } sp.ClearAttachments(); @@ -612,41 +603,61 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments attachPos = Vector3.Zero; } - List attachments = sp.GetAttachments(attachmentPt); - if (attachments.Contains(group)) + if(attachmentPt > (uint)AttachmentPoint.LastValid) { -// if (DebugLevel > 0) -// m_log.WarnFormat( -// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", -// group.Name, group.LocalId, sp.Name, attachmentPt); - + m_log.WarnFormat("[ATTACHMENTS MODULE]: Invalid attachment point {0} SP {1}", attachmentPt, sp.Name); return false; } - // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones - while (attachments.Count >= 5) - { - if (attachments[0].FromItemID != UUID.Zero) - DetachSingleAttachmentToInv(sp, attachments[0]); - attachments.RemoveAt(0); - } + List attachments = sp.GetAttachments(); + List toRemove = new List(attachments.Count); + bool doRemCheck = !append; - // If we're not appending, remove the rest as well - if (attachments.Count != 0 && !append) + for(int i = 0; i < attachments.Count; ++i) { - foreach (SceneObjectGroup g in attachments) + SceneObjectGroup sog = attachments[i]; + // duplications ? + if (group.UUID == sog.UUID) { - if (g.FromItemID != UUID.Zero) - DetachSingleAttachmentToInv(sp, g); + // if (DebugLevel > 0) + // m_log.WarnFormat( + // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", + // group.Name, group.LocalId, sp.Name, attachmentPt); + return false; + } + if(doRemCheck) + { + if(sog.AttachmentPoint == attachmentPt) + { + toRemove.Add(sog); + if(!m_wearReplacesAllOption) + doRemCheck = false; + } } } - group.DetachFromBackup(); + if(attachments.Count - toRemove.Count >= Constants.MaxAgentAttachments) + { + m_log.WarnFormat("[ATTACHMENTS MODULE]: Max attachments exceded {0}",sp.Name); + return false; + } + group.DetachFromBackup(); + group.AttachmentPoint = attachmentPt; + group.RootPart.AttachedPos = attachPos; + + // If we're not appending, remove the rest as well lock (sp.AttachmentsSyncLock) { - group.AttachmentPoint = attachmentPt; - group.RootPart.AttachedPos = attachPos; + if (toRemove.Count > 0) + { + for (int i = 0; i< toRemove.Count; ++i) + { + SceneObjectGroup g = toRemove[i]; + if (g.FromItemID != UUID.Zero) + DetachSingleAttachmentToInv(sp, g); + } + } if (addToInventory && sp.PresenceType != PresenceType.Npc) UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); @@ -668,7 +679,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // and not all scripts are loaded at this point m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); } - return true; } @@ -1255,10 +1265,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. objatt.HasGroupChanged = false; - bool tainted = false; - if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) - tainted = true; + Vector3 lastPos = objatt.RootPart.OffsetPosition; + Vector3 lastAttPos = objatt.RootPart.AttachedPos; + bool doneAttach = false; // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal // course of events. If not, then it's probably not worth trying to recover the situation // since this is more likely to trigger further exceptions and confuse later debugging. If @@ -1273,21 +1283,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments objatt.ResetOwnerChangeFlag(); } - AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); + doneAttach = AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); } catch (Exception e) { m_log.ErrorFormat( - "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", - objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); + "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", + objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); + doneAttach = false; + } + if(!doneAttach) + { // Make sure the object doesn't stick around and bail sp.RemoveAttachment(objatt); m_scene.DeleteSceneObject(objatt, false); return null; } - if (tainted) + if ((attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) || + lastPos != objatt.RootPart.OffsetPosition || + lastAttPos != objatt.RootPart.AttachedPos) objatt.HasGroupChanged = true; return objatt; diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs index 412c86e914..10d429dd17 100644 --- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs +++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs @@ -53,7 +53,6 @@ namespace OpenSim.Region.Framework.Interfaces /// All add and remove attachment operations must synchronize on this for the lifetime of their operations. /// Object AttachmentsSyncLock { get; } - int MaxNumberAttachments { get; } int GetAttachmentsCount(); /// /// The scene objects attached to this avatar. diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 070a92437e..4413d26e44 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -78,8 +78,6 @@ namespace OpenSim.Region.Framework.Scenes { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public int MaxNumberAttachments { get; } = 38; // per viewers limit - // ~ScenePresence() // { // m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs index 331f1bdc9a..6357d4f19e 100644 --- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs +++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs @@ -228,6 +228,7 @@ namespace OpenSim.Region.OptionalModules.Materials private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) { features["MaxMaterialsPerTransaction"] = m_maxMaterialsPerTransaction; + features["RenderMaterialsCapability"] = OSD.FromReal(3); } /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5d291d53c2..1591cb13bc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -14531,7 +14531,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Integer(0)); break; case ScriptBaseClass.OBJECT_ATTACHED_SLOTS_AVAILABLE: - ret.Add(new LSL_Integer(38 - av.GetAttachmentsCount())); + ret.Add(new LSL_Integer(Constants.MaxAgentAttachments - av.GetAttachmentsCount())); break; case ScriptBaseClass.OBJECT_CREATION_TIME: ret.Add(new LSL_String("")); diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs index 5806d36ba2..6f26243374 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptUThread.cs @@ -82,7 +82,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine if(callMode != XMRInstance.CallMode_SAVE) throw new Exception("callMode=" + callMode); } - catch(Exception e) + catch (Exception e) { return e; }