From 64f640f9019b0ecc65e1e2038acde306db425ebb Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 26 Aug 2014 17:37:18 +0100 Subject: [PATCH 01/15] Implement experimental non-default mechanism to update scene via a timer rather than a persistent thread with sleep. This is to see if an inaccuracy in sleep times under load is responsible for increase in frame times even when there is spare time still available. Can currently only be activated by setting "debug scene set update-on-timer true". Can be switched between timer and thread with sleep updates whilst the scene is running. --- .../ClientStack/Linden/UDP/Tests/MockScene.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 94 ++++++++++++------- OpenSim/Region/Framework/Scenes/SceneBase.cs | 3 +- .../SceneCommands/SceneCommandsModule.cs | 81 ++++++++++------ 4 files changed, 113 insertions(+), 67 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs index e2178e59be..39d1875c7b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests m_regStatus = RegionStatus.Up; } - public override void Update(int frames) {} + public override bool Update(int frames) { return true; } public override void LoadWorldMap() {} public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a43de2904d..53001e9fca 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -328,6 +328,17 @@ namespace OpenSim.Region.Framework.Scenes private Dictionary m_extraSettings; + /// + /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer + /// rather than on a single thread that sleeps. + /// + public bool UpdateOnTimer { get; set; } + + /// + /// Only used if we are updating scene on a timer rather than sleeping a thread. + /// + private Timer m_sceneUpdateTimer; + /// /// Current scene frame number /// @@ -430,7 +441,8 @@ namespace OpenSim.Region.Framework.Scenes /// Is the scene active? /// /// - /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if + /// If false, maintenance and update loops are not being run, though after setting to false update may still + /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if /// the scene is not active. /// public bool Active @@ -453,8 +465,11 @@ namespace OpenSim.Region.Framework.Scenes } private volatile bool m_active; -// private int m_lastUpdate; -// private bool m_firstHeartbeat = true; + /// + /// If true then updates are running. This may be true for a short period after a scene is de-activated. + /// + public bool IsRunning { get { return m_isRunning; } } + private volatile bool m_isRunning; private Timer m_mapGenerationTimer = new Timer(); private bool m_generateMaptiles; @@ -1352,19 +1367,18 @@ namespace OpenSim.Region.Framework.Scenes /// public void Start(bool startScripts) { + if (IsRunning) + return; + + m_isRunning = true; m_active = true; // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); - - //m_heartbeatTimer.Enabled = true; - //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); - //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); if (m_heartbeatThread != null) { m_heartbeatThread.Abort(); m_heartbeatThread = null; } -// m_lastUpdate = Util.EnvironmentTickCount(); m_heartbeatThread = Watchdog.StartThread( @@ -1401,15 +1415,6 @@ namespace OpenSim.Region.Framework.Scenes /// private void Heartbeat() { -// if (!Monitor.TryEnter(m_heartbeatLock)) -// { -// Watchdog.RemoveThread(); -// return; -// } - -// try -// { - m_eventManager.TriggerOnRegionStarted(this); // The first frame can take a very long time due to physics actors being added on startup. Therefore, @@ -1418,21 +1423,37 @@ namespace OpenSim.Region.Framework.Scenes Update(1); Watchdog.StartThread( - Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); + Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; - Update(-1); -// m_lastUpdate = Util.EnvironmentTickCount(); -// m_firstHeartbeat = false; -// } -// finally -// { -// Monitor.Pulse(m_heartbeatLock); -// Monitor.Exit(m_heartbeatLock); -// } + if (UpdateOnTimer) + { + m_sceneUpdateTimer = new Timer(MinFrameTime * 1000); + m_sceneUpdateTimer.AutoReset = true; + m_sceneUpdateTimer.Elapsed += Update; + m_sceneUpdateTimer.Start(); + } + else + { + Update(-1); + Watchdog.RemoveThread(); + m_isRunning = false; + } + } - Watchdog.RemoveThread(); + private void Update(object sender, ElapsedEventArgs e) + { + // If the last frame did not complete on time, then immediately start the next update on the same thread + // and ignore further timed updates until we have a frame that had spare time. + while (!Update(1) && Active) {} + + if (!Active || m_shuttingDown) + { + m_sceneUpdateTimer.Stop(); + m_sceneUpdateTimer = null; + m_isRunning = false; + } } private void Maintenance() @@ -1502,7 +1523,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public override void Update(int frames) + public override bool Update(int frames) { long? endFrame = null; @@ -1652,7 +1673,8 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerRegionHeartbeatEnd(this); - Watchdog.UpdateThread(); + if (!UpdateOnTimer) + Watchdog.UpdateThread(); previousFrameTick = m_lastFrameTick; m_lastFrameTick = Util.EnvironmentTickCount(); @@ -1661,9 +1683,11 @@ namespace OpenSim.Region.Framework.Scenes if (tmpMS > 0) { - Thread.Sleep(tmpMS); - spareMS += tmpMS; - } + spareMS = tmpMS; + + if (!UpdateOnTimer) + Thread.Sleep(tmpMS); + } frameMS = Util.EnvironmentTickCountSubtract(maintc); maintc = Util.EnvironmentTickCount(); @@ -1683,7 +1707,7 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.AddSpareMS(spareMS); StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); - // Optionally warn if a frame takes double the amount of time that it should. + // Optionally warn if a frame takes double the amount of time that it should. if (DebugUpdates && Util.EnvironmentTickCountSubtract( m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) @@ -1693,6 +1717,8 @@ namespace OpenSim.Region.Framework.Scenes MinFrameTime * 1000, RegionInfo.RegionName); } + + return spareMS >= 0; } public void AddGroupTarget(SceneObjectGroup grp) diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 0445268315..aaddce6050 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -196,7 +196,8 @@ namespace OpenSim.Region.Framework.Scenes /// Number of frames to update. Exits on shutdown even if there are frames remaining. /// If -1 then updates until shutdown. /// - public abstract void Update(int frames); + /// true if update completed within minimum frame time, false otherwise. + public abstract bool Update(int frames); #endregion diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs index f2595c8517..0927c4ffd6 100644 --- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; +using System.Threading; using log4net; using Mono.Addins; using Nini.Config; @@ -93,42 +94,44 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments "Debug", this, "debug scene get", "debug scene get", "List current scene options.", - "active - if false then main scene update and maintenance loops are suspended.\n" - + "animations - if true then extra animations debug information is logged.\n" - + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" - + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" - + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" - + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" - + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" - + "collisions - if false then collisions with other objects are turned off.\n" - + "pbackup - if false then periodic scene backup is turned off.\n" - + "physics - if false then all physics objects are non-physical.\n" - + "scripting - if false then no scripting operations happen.\n" - + "teleport - if true then some extra teleport debug information is logged.\n" - + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", + "active - if false then main scene update and maintenance loops are suspended.\n" + + "animations - if true then extra animations debug information is logged.\n" + + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" + + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" + + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" + + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" + + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" + + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" + + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" + + "collisions - if false then collisions with other objects are turned off.\n" + + "pbackup - if false then periodic scene backup is turned off.\n" + + "physics - if false then all physics objects are non-physical.\n" + + "scripting - if false then no scripting operations happen.\n" + + "teleport - if true then some extra teleport debug information is logged.\n" + + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n" + + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", HandleDebugSceneGetCommand); scene.AddCommand( "Debug", this, "debug scene set", - "debug scene set active|collisions|pbackup|physics|scripting|teleport|updates true|false", + "debug scene set ", "Turn on scene debugging options.", - "active - if false then main scene update and maintenance loops are suspended.\n" - + "animations - if true then extra animations debug information is logged.\n" - + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" - + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" - + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" - + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" - + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" - + "collisions - if false then collisions with other objects are turned off.\n" - + "pbackup - if false then periodic scene backup is turned off.\n" - + "physics - if false then all physics objects are non-physical.\n" - + "scripting - if false then no scripting operations happen.\n" - + "teleport - if true then some extra teleport debug information is logged.\n" - + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", + "active - if false then main scene update and maintenance loops are suspended.\n" + + "animations - if true then extra animations debug information is logged.\n" + + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" + + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" + + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" + + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" + + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" + + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" + + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" + + "collisions - if false then collisions with other objects are turned off.\n" + + "pbackup - if false then periodic scene backup is turned off.\n" + + "physics - if false then all physics objects are non-physical.\n" + + "scripting - if false then no scripting operations happen.\n" + + "teleport - if true then some extra teleport debug information is logged.\n" + + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n" + + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", HandleDebugSceneSetCommand); } @@ -163,6 +166,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments cdl.AddRow("physics", m_scene.PhysicsEnabled); cdl.AddRow("scripting", m_scene.ScriptsEnabled); cdl.AddRow("teleport", m_scene.DebugTeleporting); + cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer); cdl.AddRow("updates", m_scene.DebugUpdates); MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name); @@ -304,6 +308,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments m_scene.DebugTeleporting = enableTeleportDebugging; } + if (options.ContainsKey("update-on-timer")) + { + bool enableUpdateOnTimer; + if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer)) + { + m_scene.UpdateOnTimer = enableUpdateOnTimer; + m_scene.Active = false; + + while (m_scene.IsRunning) + Thread.Sleep(20); + + m_scene.Active = true; + } + } + if (options.ContainsKey("updates")) { bool enableUpdateDebugging; From 42bb122232e1c170dd89ec45fbb19256ef09aa9e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 26 Aug 2014 18:13:00 +0100 Subject: [PATCH 02/15] Fix frame times when updating scene on timer. --- OpenSim/Region/Framework/Scenes/Scene.cs | 32 +++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 53001e9fca..de89cc231d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1426,6 +1426,7 @@ namespace OpenSim.Region.Framework.Scenes Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; + m_lastFrameTick = Util.EnvironmentTickCount(); if (UpdateOnTimer) { @@ -1532,7 +1533,6 @@ namespace OpenSim.Region.Framework.Scenes float physicsFPS = 0f; int previousFrameTick, tmpMS; - int maintc = Util.EnvironmentTickCount(); while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) { @@ -1672,27 +1672,29 @@ namespace OpenSim.Region.Framework.Scenes } EventManager.TriggerRegionHeartbeatEnd(this); + otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; if (!UpdateOnTimer) + { Watchdog.UpdateThread(); - previousFrameTick = m_lastFrameTick; - m_lastFrameTick = Util.EnvironmentTickCount(); - tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); - tmpMS = (int)(MinFrameTime * 1000) - tmpMS; + tmpMS = Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), m_lastFrameTick); + tmpMS = (int)(MinFrameTime * 1000) - tmpMS; - if (tmpMS > 0) - { - spareMS = tmpMS; - - if (!UpdateOnTimer) + if (tmpMS > 0) + { + spareMS = tmpMS; Thread.Sleep(tmpMS); - } + } + } + else + { + spareMS = Math.Max(0, (int)(MinFrameTime * 1000) - physicsMS2 - agentMS - physicsMS -otherMS); + } - frameMS = Util.EnvironmentTickCountSubtract(maintc); - maintc = Util.EnvironmentTickCount(); - - otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; + previousFrameTick = m_lastFrameTick; + frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); + m_lastFrameTick = Util.EnvironmentTickCount(); // if (Frame%m_update_avatars == 0) // UpdateInWorldTime(); From bafa82eb12070279090b76fb6d38fda1c29ab859 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 26 Aug 2014 18:25:14 +0100 Subject: [PATCH 03/15] Remove race conditions from where SP.AbsolutePosition could change between the various property checks. --- .../CoreModules/World/Land/LandManagementModule.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 55ef61d8a9..11b079f091 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -525,16 +525,13 @@ namespace OpenSim.Region.CoreModules.World.Land /// /// public void EventManagerOnClientMovement(ScenePresence avatar) - // { - ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + Vector3 pos = avatar.AbsolutePosition; + ILandObject over = GetLandObject(pos.X, pos.Y); if (over != null) { - if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)) - { - avatar.lastKnownAllowedPosition = - new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); - } + if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || pos.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)) + avatar.lastKnownAllowedPosition = pos; } } From b1ff78f4d8265dbb3e8f5bc1d1c9cfad284f7ef3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 26 Aug 2014 18:52:09 +0100 Subject: [PATCH 04/15] Don't allow update timer to invoke another scene update if the previous is still active. --- OpenSim/Region/Framework/Scenes/Scene.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index de89cc231d..e87500ac85 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1443,8 +1443,15 @@ namespace OpenSim.Region.Framework.Scenes } } + private volatile bool m_isTimerUpdateRunning; + private void Update(object sender, ElapsedEventArgs e) - { + { + if (m_isTimerUpdateRunning) + return; + + m_isTimerUpdateRunning = true; + // If the last frame did not complete on time, then immediately start the next update on the same thread // and ignore further timed updates until we have a frame that had spare time. while (!Update(1) && Active) {} @@ -1455,6 +1462,8 @@ namespace OpenSim.Region.Framework.Scenes m_sceneUpdateTimer = null; m_isRunning = false; } + + m_isTimerUpdateRunning = false; } private void Maintenance() From f132f642b23d9d0c336354a0bc4bb95c41023c34 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 28 Aug 2014 18:15:33 +0100 Subject: [PATCH 05/15] On code section that rezzes single objects and attachments, reduce CPU use by reading asset XML a single time with a stream reader rather than multiple times. Reading large XML documents (e.g. complex attachments) is CPU expensive - this must be done as few times as possible (preferably just once). Reading these documents into XmlDocument is also more resource intensive than using XmlTextReader, as per Microsoft's own publication "Improve .NET Application Performance and Scalability" Optimization of other cases will follow if this change is successful. --- .../InventoryAccess/InventoryAccessModule.cs | 6 +- .../Tests/InventoryAccessModuleTests.cs | 1 + .../Framework/Scenes/Scene.Inventory.cs | 95 ++++++++++++------- .../Framework/Scenes/SceneObjectGroup.cs | 28 ++++++ .../Serialization/SceneObjectSerializer.cs | 67 ++++++------- 5 files changed, 127 insertions(+), 70 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index b4771fd2ca..8528c65f32 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -798,7 +798,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { - AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); + AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); if (rezAsset == null) { @@ -829,7 +829,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); Vector3 pos; - bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight); + bool single + = m_Scene.GetObjectsToRez( + rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight); if (single) { diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index ad1a0e1a96..80b9c0af78 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -111,6 +111,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests InventoryFolderBase objsFolder = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; item1.Folder = objsFolder.ID; + item1.Flags |= (uint)InventoryItemFlags.ObjectHasMultipleItems; m_scene.AddInventoryItem(item1); SceneObjectGroup so diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 542d454629..cbb4fe771a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Collections; using System.Reflection; using System.Text; +using System.Threading; using System.Timers; using System.Xml; using OpenMetaverse; @@ -2192,60 +2193,84 @@ namespace OpenSim.Region.Framework.Scenes /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object. /// /// Asset data - /// Whether the item is an attachment + /// True if the object is an attachment. /// The objects included in the asset /// Relative positions of the objects /// Bounding box of all the objects /// Offset in the Z axis from the centre of the bounding box /// to the centre of the root prim (relevant only when returning a single object) - /// true = returning a single object; false = multiple objects - public bool GetObjectsToRez(byte[] assetData, bool attachment, out List objlist, out List veclist, + /// + /// true if returning a single object or deserialization fails, false if returning the coalesced + /// list of objects + /// + public bool GetObjectsToRez( + byte[] assetData, bool isAttachment, out List objlist, out List veclist, out Vector3 bbox, out float offsetHeight) { objlist = new List(); veclist = new List(); - XmlDocument doc = new XmlDocument(); string xmlData = Utils.BytesToString(assetData); - doc.LoadXml(xmlData); - XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); - if (e == null || attachment) // Single + try { - SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - objlist.Add(g); - veclist.Add(new Vector3(0, 0, 0)); - bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); - return true; - } - else - { - XmlElement coll = (XmlElement)e; - float bx = Convert.ToSingle(coll.GetAttribute("x")); - float by = Convert.ToSingle(coll.GetAttribute("y")); - float bz = Convert.ToSingle(coll.GetAttribute("z")); - bbox = new Vector3(bx, by, bz); - offsetHeight = 0; - - XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); - foreach (XmlNode n in groups) + using (XmlTextReader reader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) { - SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); - objlist.Add(g); + reader.Read(); + bool isSingleObject = reader.Name != "CoalescedObject"; - XmlElement el = (XmlElement)n; - string rawX = el.GetAttribute("offsetx"); - string rawY = el.GetAttribute("offsety"); - string rawZ = el.GetAttribute("offsetz"); + if (isSingleObject || isAttachment) + { + SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(reader); + objlist.Add(g); + veclist.Add(Vector3.Zero); + bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); + return true; + } + else + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlData); + XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); + XmlElement coll = (XmlElement)e; + float bx = Convert.ToSingle(coll.GetAttribute("x")); + float by = Convert.ToSingle(coll.GetAttribute("y")); + float bz = Convert.ToSingle(coll.GetAttribute("z")); + bbox = new Vector3(bx, by, bz); + offsetHeight = 0; - float x = Convert.ToSingle(rawX); - float y = Convert.ToSingle(rawY); - float z = Convert.ToSingle(rawZ); - veclist.Add(new Vector3(x, y, z)); + XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); + foreach (XmlNode n in groups) + { + SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); + objlist.Add(g); + + XmlElement el = (XmlElement)n; + string rawX = el.GetAttribute("offsetx"); + string rawY = el.GetAttribute("offsety"); + string rawZ = el.GetAttribute("offsetz"); + + float x = Convert.ToSingle(rawX); + float y = Convert.ToSingle(rawY); + float z = Convert.ToSingle(rawZ); + veclist.Add(new Vector3(x, y, z)); + } + + return false; + } } } + catch (Exception e) + { + m_log.Error( + "[AGENT INVENTORY]: Deserialization of xml failed when looking for CoalescedObject tag. Exception ", + e); - return false; + bbox = Vector3.Zero; + offsetHeight = 0; + } + + return true; } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 69491b7e1d..c95d2076a4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -902,6 +902,34 @@ namespace OpenSim.Region.Framework.Scenes } } + public void LoadScriptState(XmlTextReader reader) + { +// m_log.DebugFormat("[SCENE OBJECT GROUP]: Looking for script state for {0} in {1}", Name); + + while (reader.ReadToFollowing("SavedScriptState")) + { +// m_log.DebugFormat("[SCENE OBJECT GROUP]: Loading script state for {0}", Name); + + if (m_savedScriptState == null) + m_savedScriptState = new Dictionary(); + + string uuid = reader.GetAttribute("UUID"); + + if (uuid != null) + { +// m_log.DebugFormat("[SCENE OBJECT GROUP]: Found state for item ID {0} in object {1}", uuid, Name); + + UUID itemid = new UUID(uuid); + if (itemid != UUID.Zero) + m_savedScriptState[itemid] = reader.ReadInnerXml(); + } + else + { + m_log.WarnFormat("[SCENE OBJECT GROUP]: SavedScriptState element had no UUID in object {0}", Name); + } + } + } + /// /// Hooks this object up to the backup event so that it is persisted to the database when the update thread executes. /// diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index e68f954956..8f99dc6f8e 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -58,58 +58,59 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// /// The scene object deserialized. Null on failure. public static SceneObjectGroup FromOriginalXmlFormat(string xmlData) + { + using (XmlTextReader reader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) + return FromOriginalXmlFormat(reader); + } + + /// + /// Deserialize a scene object from the original xml format + /// + /// + /// The scene object deserialized. Null on failure. + public static SceneObjectGroup FromOriginalXmlFormat(XmlTextReader reader) { //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); //int time = System.Environment.TickCount; + SceneObjectGroup sceneObject = null; + try { - StringReader sr; - XmlTextReader reader; - XmlNodeList parts; - XmlDocument doc; int linkNum; - doc = new XmlDocument(); - doc.LoadXml(xmlData); - parts = doc.GetElementsByTagName("RootPart"); + reader.ReadToFollowing("RootPart"); + reader.ReadToFollowing("SceneObjectPart"); + sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader)); + reader.ReadToFollowing("OtherParts"); - if (parts.Count == 0) - throw new Exception("Invalid Xml format - no root part"); - - sr = new StringReader(parts[0].InnerXml); - reader = new XmlTextReader(sr); - SceneObjectGroup sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader)); - reader.Close(); - sr.Close(); - - parts = doc.GetElementsByTagName("Part"); - - for (int i = 0; i < parts.Count; i++) + if (reader.ReadToDescendant("Part")) { - sr = new StringReader(parts[i].InnerXml); - reader = new XmlTextReader(sr); - SceneObjectPart part = SceneObjectPart.FromXml(reader); - linkNum = part.LinkNum; - sceneObject.AddPart(part); - part.LinkNum = linkNum; - part.TrimPermissions(); - reader.Close(); - sr.Close(); + do + { + if (reader.ReadToDescendant("SceneObjectPart")) + { + SceneObjectPart part = SceneObjectPart.FromXml(reader); + linkNum = part.LinkNum; + sceneObject.AddPart(part); + part.LinkNum = linkNum; + part.TrimPermissions(); + } + } + while (reader.ReadToNextSibling("Part")); } // Script state may, or may not, exist. Not having any, is NOT // ever a problem. - sceneObject.LoadScriptState(doc); - - return sceneObject; + sceneObject.LoadScriptState(reader); } catch (Exception e) { - m_log.ErrorFormat( - "[SERIALIZER]: Deserialization of xml failed with {0}. xml was {1}", e, xmlData); + m_log.ErrorFormat("[SERIALIZER]: Deserialization of xml failed. Exception {0}", e); return null; } + + return sceneObject; } /// From 1a3ffda8524cfd19e1149a1831cf8e8defa97a57 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 28 Aug 2014 18:37:34 +0100 Subject: [PATCH 06/15] minor: Eliminate more unnecessary code copying individual parameters for Vector3 copying in Scene - this is not necessary as Vector3 is a value type --- OpenSim/Region/Framework/Scenes/Scene.cs | 36 +++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e87500ac85..18376c317e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2110,8 +2110,8 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart target = GetSceneObjectPart(RayTargetID); Vector3 direction = Vector3.Normalize(RayEnd - RayStart); - Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z); - Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z); + Vector3 AXOrigin = RayStart; + Vector3 AXdirection = direction; if (target != null) { @@ -2127,19 +2127,19 @@ namespace OpenSim.Region.Framework.Scenes EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); // Un-comment out the following line to Get Raytrace results printed to the console. - // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); float ScaleOffset = 0.5f; // If we hit something if (ei.HitTF) { - Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z); + Vector3 scaleComponent = ei.AAfaceNormal; if (scaleComponent.X != 0) ScaleOffset = scale.X; if (scaleComponent.Y != 0) ScaleOffset = scale.Y; if (scaleComponent.Z != 0) ScaleOffset = scale.Z; ScaleOffset = Math.Abs(ScaleOffset); - Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); - Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z); + Vector3 intersectionpoint = ei.ipoint; + Vector3 normal = ei.normal; // Set the position to the intersection point Vector3 offset = (normal * (ScaleOffset / 2f)); pos = (intersectionpoint + offset); @@ -2164,8 +2164,9 @@ namespace OpenSim.Region.Framework.Scenes if (ei.HitTF) { - pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); - } else + pos = ei.ipoint; + } + else { // fall back to our stupid functionality pos = RayEnd; @@ -3218,8 +3219,8 @@ namespace OpenSim.Region.Framework.Scenes if (target != null && target2 != null) { Vector3 direction = Vector3.Normalize(RayEnd - RayStart); - Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z); - Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z); + Vector3 AXOrigin = RayStart; + Vector3 AXdirection = direction; pos = target2.AbsolutePosition; //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); @@ -3240,13 +3241,13 @@ namespace OpenSim.Region.Framework.Scenes if (ei.HitTF) { Vector3 scale = target.Scale; - Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z); + Vector3 scaleComponent = ei.AAfaceNormal; if (scaleComponent.X != 0) ScaleOffset = scale.X; if (scaleComponent.Y != 0) ScaleOffset = scale.Y; if (scaleComponent.Z != 0) ScaleOffset = scale.Z; ScaleOffset = Math.Abs(ScaleOffset); - Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); - Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z); + Vector3 intersectionpoint = ei.ipoint; + Vector3 normal = ei.normal; Vector3 offset = normal * (ScaleOffset / 2f); pos = intersectionpoint + offset; @@ -3266,6 +3267,7 @@ namespace OpenSim.Region.Framework.Scenes { copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); } + if (copy != null) EventManager.TriggerObjectAddedToScene(copy); } @@ -5098,7 +5100,7 @@ namespace OpenSim.Region.Framework.Scenes case PhysicsJointType.Ball: { Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); - Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z); + Vector3 proxyPos = jointAnchor; jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update } break; @@ -5123,7 +5125,7 @@ namespace OpenSim.Region.Framework.Scenes jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); } - Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z); + Vector3 proxyPos = jointAnchor; Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update @@ -5224,8 +5226,8 @@ namespace OpenSim.Region.Framework.Scenes y = Heightmap.Height - 1; Vector3 p0 = new Vector3(x, y, (float)Heightmap[(int)x, (int)y]); - Vector3 p1 = new Vector3(p0); - Vector3 p2 = new Vector3(p0); + Vector3 p1 = p0; + Vector3 p2 = p0; p1.X += 1.0f; if (p1.X < Heightmap.Width) From 305c3e668a36f8a53582d57a0eee79084c62a280 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 29 Aug 2014 18:06:29 +0100 Subject: [PATCH 07/15] Add regression test for deserializing xml objects with more than one non-root part. --- .../World/Serialiser/Tests/SerialiserTests.cs | 531 +++++++++++++----- 1 file changed, 405 insertions(+), 126 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index 66059fb8bb..52203f76cc 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs @@ -27,6 +27,7 @@ using System.Collections.Generic; using System.IO; +using System.Text; using System.Xml; using log4net.Config; using NUnit.Framework; @@ -42,128 +43,351 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests [TestFixture] public class SerialiserTests : OpenSimTestCase { - private string xml = @" - - - - false - a6dacf01-4636-4bb9-8a97-30609438af9d - e6a5a05e-e8cc-4816-8701-04165e335790 - 1 - - 0 - e6a5a05e-e8cc-4816-8701-04165e335790 - 2698615125 - PrimMyRide - 0 - false - 1099511628032000 - 0 - 147.2392.69822.78084 - 000 - -4.371139E-08-1-4.371139E-080 - 000 - 000 - 000 - 000 - - - - - - 0 - 0 - - 1 - AAAAAAAAERGZmQAAAAAABQCVlZUAAAAAQEAAAABAQAAAAAAAAAAAAAAAAAAAAA== - AA== - 0 - 16 - 0 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 9 - 0 - 0 - 0 - 10100.5 - 0 - Square - Same - 00000000-0000-0000-0000-000000000000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - false - false - false - - 10100.5 - 0 - 0001 - 000 - 000 - 0001 - 0 - 1211330445 - 0 - 0 - 0 - 0 - 00000000-0000-0000-0000-000000000000 - a6dacf01-4636-4bb9-8a97-30609438af9d - a6dacf01-4636-4bb9-8a97-30609438af9d - 2147483647 - 2147483647 - 0 - 0 - 2147483647 - None - 00000000-0000-0000-0000-000000000000 - 0 - - - - MyNamespace - - MyStore - - the answer - 42 - - + private const string ObjectRootPartStubXml = +@" + + + false + a6dacf01-4636-4bb9-8a97-30609438af9d + e6a5a05e-e8cc-4816-8701-04165e335790 + 1 + + 0 + e6a5a05e-e8cc-4816-8701-04165e335790 + 2698615125 + PrimMyRide + 0 + false + 1099511628032000 + 0 + 147.2392.69822.78084 + 000 + -4.371139E-08-1-4.371139E-080 + 000 + 000 + 000 + 000 + + + + + + 0 + 0 + + 1 + AAAAAAAAERGZmQAAAAAABQCVlZUAAAAAQEAAAABAQAAAAAAAAAAAAAAAAAAAAA== + AA== + 0 + 16 + 0 + 0 + 0 + 100 + 100 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 9 + 0 + 0 + 0 + 10100.5 + 0 + Square + Same + 00000000-0000-0000-0000-000000000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + false + false + false + + 10100.5 + 0 + 0001 + 000 + 000 + 0001 + 0 + 1211330445 + 0 + 0 + 0 + 0 + 00000000-0000-0000-0000-000000000000 + a6dacf01-4636-4bb9-8a97-30609438af9d + a6dacf01-4636-4bb9-8a97-30609438af9d + 2147483647 + 2147483647 + 0 + 0 + 2147483647 + None + 00000000-0000-0000-0000-000000000000 + 0 + + + + MyNamespace + + MyStore + + the answer + 42 - - - - - - "; + + + + + + "; - private string badFloatsXml = @" + private const string ObjectWithNoOtherPartsXml = ObjectRootPartStubXml + +@" + +"; + + private const string ObjectWithOtherPartsXml = ObjectRootPartStubXml + +@" + + + + false + a6dacf01-4636-4bb9-8a97-30609438af9d + 9958feb1-02a6-49e4-a4ce-eba6f578ee13 + 3 + 9958feb1-02a6-49e4-a4ce-eba6f578ee13 + 1154704500 + Alien Head 1 + 3 + false + false + 21990232560640000 + 0 + 125.5655127.34622.48036 + -0.21719360.10839840.0009994507 + -0.51221060.4851225-0.49574540.5064908 + 000 + 000 + 000 + (No Description) + 000255 + + + + 253 + 0 + + 5 + Vw3dpvgTRUOiIUOGsnpWlAB/f38AAAAAgL8AAACAPwAAAAAAAAAF4ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AA== + 0 + 32 + 0 + 0 + 0 + 100 + 100 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 9 + 0 + 0 + 0 + 9 + 0 + HalfCircle + Same + 00000000-0000-0000-0000-000000000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + false + false + false + + 0.11481950.01438910.02768878 + 0001 + 000 + 000 + 0001 + 1154704499 + 1256611042 + 0 + 10 + 0 + 0 + 00000000-0000-0000-0000-000000000000 + 7b2022f0-5f19-488c-b7e5-829d8f96b448 + 7b2022f0-5f19-488c-b7e5-829d8f96b448 + 647168 + 647168 + 0 + 0 + 581632 + None + 00000000-0000-0000-0000-000000000000 + 0 + 000 + + + -2 + -2 + -2 + -2 + -2 + + + + + false + a6dacf01-4636-4bb9-8a97-30609438af9d + 674b6b86-f5aa-439a-8e00-0d75bc08c80a + 3 + 674b6b86-f5aa-439a-8e00-0d75bc08c80a + 1154704501 + Alien Head 2 + 3 + false + false + 21990232560640000 + 0 + 125.5655127.34622.48036 + -0.24909970.085201260.0009002686 + -0.47653680.5194498-0.53013720.4712104 + 000 + 000 + 000 + (No Description) + 000255 + + + + 252 + 0 + + 0 + Vw3dpvgTRUOiIUOGsnpWlAB/f38AAAAAgL8AAACAPwAAAAAAAAAF4ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AA== + 0 + 32 + 0 + 0 + 0 + 100 + 150 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 9 + 0 + 0 + 0 + 9 + 0 + Circle + Same + 00000000-0000-0000-0000-000000000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + false + false + false + + 0.035743850.059580320.04764182 + 0001 + 000 + 000 + 0001 + 1154704499 + 1256611042 + 0 + 10 + 0 + 0 + 00000000-0000-0000-0000-000000000000 + 7b2022f0-5f19-488c-b7e5-829d8f96b448 + 7b2022f0-5f19-488c-b7e5-829d8f96b448 + 647168 + 647168 + 0 + 0 + 581632 + None + 00000000-0000-0000-0000-000000000000 + 0 + 000 + + + -2 + -2 + -2 + -2 + -2 + + + +"; + + private const string ObjectWithBadFloatsXml = @" @@ -270,7 +494,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests "; - private string xml2 = @" + private const string ObjectWithNoPartsXml2 = @" b46ef588-411e-4a8b-a284-d7dcfe8e74ef @@ -377,12 +601,12 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests } [Test] - public void TestDeserializeXml() + public void TestDeserializeXmlObjectWithNoOtherParts() { TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); + TestHelpers.EnableLogging(); - SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(xml); + SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithNoOtherPartsXml); SceneObjectPart rootPart = so.RootPart; Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); @@ -394,13 +618,68 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests // TODO: Check other properties } + [Test] + public void TestDeserializeXmlObjectWithOtherParts() + { + TestHelpers.InMethod(); + TestHelpers.EnableLogging(); + + // We need to do this to get rid of whitespace between elements. + // TODO: Ultimately OpenSimulator xml parser should be set to ignore this but this means a bit of + // rejigging to replace old new XmlTextReader() with the post .NET 2.0 XmlReader.Create() calls + XmlDocument xdoc = new XmlDocument(); + xdoc.LoadXml(ObjectWithOtherPartsXml); + + StringBuilder sb = new StringBuilder(); + using (StringWriter sw = new StringWriter(sb)) + { + using (XmlTextWriter xtw = new XmlTextWriter(sw)) + { + xtw.Formatting = Formatting.Indented; + xdoc.WriteTo(xtw); + } + } + + SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(sb.ToString()); + SceneObjectPart[] parts = so.Parts; + Assert.AreEqual(3, so.Parts.Length); + + { + SceneObjectPart part = parts[0]; + + Assert.That(part.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); + Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); + Assert.That(part.Name, Is.EqualTo("PrimMyRide")); + OSDMap store = part.DynAttrs.GetStore("MyNamespace", "MyStore"); + Assert.AreEqual(42, store["the answer"].AsInteger()); + } + + { + SceneObjectPart part = parts[1]; + + Assert.That(part.UUID, Is.EqualTo(new UUID("9958feb1-02a6-49e4-a4ce-eba6f578ee13"))); + Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); + Assert.That(part.Name, Is.EqualTo("Alien Head 1")); + } + + { + SceneObjectPart part = parts[2]; + + Assert.That(part.UUID, Is.EqualTo(new UUID("674b6b86-f5aa-439a-8e00-0d75bc08c80a"))); + Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); + Assert.That(part.Name, Is.EqualTo("Alien Head 2")); + } + + // TODO: Check other properties + } + [Test] public void TestDeserializeBadFloatsXml() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(badFloatsXml); + SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithBadFloatsXml); SceneObjectPart rootPart = so.RootPart; Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); @@ -517,7 +796,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests TestHelpers.InMethod(); //log4net.Config.XmlConfigurator.Configure(); - SceneObjectGroup so = m_serialiserModule.DeserializeGroupFromXml2(xml2); + SceneObjectGroup so = m_serialiserModule.DeserializeGroupFromXml2(ObjectWithNoPartsXml2); SceneObjectPart rootPart = so.RootPart; Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); From 3555c0c3f3306de5dbdf504f595a1f6abc032374 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 29 Aug 2014 18:14:47 +0100 Subject: [PATCH 08/15] Fix recent regression test TestDeserializeXmlObjectWithOtherParts() which was not meant to indent the input xml --- .../CoreModules/World/Serialiser/Tests/SerialiserTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index 52203f76cc..94cd9cd9dd 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs @@ -635,7 +635,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests { using (XmlTextWriter xtw = new XmlTextWriter(sw)) { - xtw.Formatting = Formatting.Indented; +// xtw.Formatting = Formatting.Indented; xdoc.WriteTo(xtw); } } From 1b75ec5647afeb9fbdad78f70c0c90a829bba076 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 29 Aug 2014 19:08:23 +0100 Subject: [PATCH 09/15] Ignore whitespace when reading serialized XML objects. This was previously effectively being done by XmlDocument in the multiple passes through the XML. This change tells XmlReader to ignore whitespace. This also means changing arguments to use XmlReader instead of XmlTextReader (a descendent of XmlReader) directly. XmlReader.Create() has been the recommend way to create XML readers since .NET 2.0 as per MS SDK and is the only way to specific ignore whitespace settings. --- .../External/ExternalRepresentationUtils.cs | 8 +- .../External/LandDataSerializer.cs | 10 +- .../External/UserInventoryItemSerializer.cs | 44 +-- OpenSim/Framework/Util.cs | 10 +- .../World/Serialiser/Tests/SerialiserTests.cs | 18 +- .../Framework/Scenes/Scene.Inventory.cs | 75 ++--- .../Framework/Scenes/SceneObjectGroup.cs | 2 +- .../Framework/Scenes/SceneObjectPart.cs | 2 +- .../Serialization/SceneObjectSerializer.cs | 299 +++++++++--------- 9 files changed, 228 insertions(+), 240 deletions(-) diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs index db46ea8735..6debf6531e 100644 --- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs +++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs @@ -51,7 +51,7 @@ namespace OpenSim.Framework.Serialization.External /// /// true on successful, false if there were any processing failures public static bool ExecuteReadProcessors( - NodeType nodeToFill, Dictionary> processors, XmlTextReader xtr) + NodeType nodeToFill, Dictionary> processors, XmlReader xtr) { return ExecuteReadProcessors( nodeToFill, @@ -75,8 +75,8 @@ namespace OpenSim.Framework.Serialization.External /// true on successful, false if there were any processing failures public static bool ExecuteReadProcessors( NodeType nodeToFill, - Dictionary> processors, - XmlTextReader xtr, + Dictionary> processors, + XmlReader xtr, Action parseExceptionAction) { bool errors = false; @@ -88,7 +88,7 @@ namespace OpenSim.Framework.Serialization.External // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName); - Action p = null; + Action p = null; if (processors.TryGetValue(xtr.Name, out p)) { // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName); diff --git a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs index 4b5326a7fc..e42d56f96b 100644 --- a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs +++ b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs @@ -44,11 +44,11 @@ namespace OpenSim.Framework.Serialization.External { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static Dictionary> m_ldProcessors - = new Dictionary>(); + private static Dictionary> m_ldProcessors + = new Dictionary>(); - private static Dictionary> m_laeProcessors - = new Dictionary>(); + private static Dictionary> m_laeProcessors + = new Dictionary>(); static LandDataSerializer() { @@ -134,7 +134,7 @@ namespace OpenSim.Framework.Serialization.External "AccessList", (lae, xtr) => lae.Flags = (AccessList)Convert.ToUInt32(xtr.ReadElementString("AccessList"))); } - public static void ProcessParcelAccessList(LandData ld, XmlTextReader xtr) + public static void ProcessParcelAccessList(LandData ld, XmlReader xtr) { if (!xtr.IsEmptyElement) { diff --git a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs index 135cefb616..994cede575 100644 --- a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs +++ b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs @@ -46,8 +46,8 @@ namespace OpenSim.Framework.Serialization.External { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static Dictionary> m_InventoryItemXmlProcessors - = new Dictionary>(); + private static Dictionary> m_InventoryItemXmlProcessors + = new Dictionary>(); #region InventoryItemBase Processor initialization static UserInventoryItemSerializer() @@ -76,103 +76,103 @@ namespace OpenSim.Framework.Serialization.External #endregion #region InventoryItemBase Processors - private static void ProcessName(InventoryItemBase item, XmlTextReader reader) + private static void ProcessName(InventoryItemBase item, XmlReader reader) { item.Name = reader.ReadElementContentAsString("Name", String.Empty); } - private static void ProcessID(InventoryItemBase item, XmlTextReader reader) + private static void ProcessID(InventoryItemBase item, XmlReader reader) { item.ID = Util.ReadUUID(reader, "ID"); } - private static void ProcessInvType(InventoryItemBase item, XmlTextReader reader) + private static void ProcessInvType(InventoryItemBase item, XmlReader reader) { item.InvType = reader.ReadElementContentAsInt("InvType", String.Empty); } - private static void ProcessCreatorUUID(InventoryItemBase item, XmlTextReader reader) + private static void ProcessCreatorUUID(InventoryItemBase item, XmlReader reader) { item.CreatorId = reader.ReadElementContentAsString("CreatorUUID", String.Empty); } - private static void ProcessCreatorID(InventoryItemBase item, XmlTextReader reader) + private static void ProcessCreatorID(InventoryItemBase item, XmlReader reader) { // when it exists, this overrides the previous item.CreatorId = reader.ReadElementContentAsString("CreatorID", String.Empty); } - private static void ProcessCreationDate(InventoryItemBase item, XmlTextReader reader) + private static void ProcessCreationDate(InventoryItemBase item, XmlReader reader) { item.CreationDate = reader.ReadElementContentAsInt("CreationDate", String.Empty); } - private static void ProcessOwner(InventoryItemBase item, XmlTextReader reader) + private static void ProcessOwner(InventoryItemBase item, XmlReader reader) { item.Owner = Util.ReadUUID(reader, "Owner"); } - private static void ProcessDescription(InventoryItemBase item, XmlTextReader reader) + private static void ProcessDescription(InventoryItemBase item, XmlReader reader) { item.Description = reader.ReadElementContentAsString("Description", String.Empty); } - private static void ProcessAssetType(InventoryItemBase item, XmlTextReader reader) + private static void ProcessAssetType(InventoryItemBase item, XmlReader reader) { item.AssetType = reader.ReadElementContentAsInt("AssetType", String.Empty); } - private static void ProcessAssetID(InventoryItemBase item, XmlTextReader reader) + private static void ProcessAssetID(InventoryItemBase item, XmlReader reader) { item.AssetID = Util.ReadUUID(reader, "AssetID"); } - private static void ProcessSaleType(InventoryItemBase item, XmlTextReader reader) + private static void ProcessSaleType(InventoryItemBase item, XmlReader reader) { item.SaleType = (byte)reader.ReadElementContentAsInt("SaleType", String.Empty); } - private static void ProcessSalePrice(InventoryItemBase item, XmlTextReader reader) + private static void ProcessSalePrice(InventoryItemBase item, XmlReader reader) { item.SalePrice = reader.ReadElementContentAsInt("SalePrice", String.Empty); } - private static void ProcessBasePermissions(InventoryItemBase item, XmlTextReader reader) + private static void ProcessBasePermissions(InventoryItemBase item, XmlReader reader) { item.BasePermissions = (uint)reader.ReadElementContentAsInt("BasePermissions", String.Empty); } - private static void ProcessCurrentPermissions(InventoryItemBase item, XmlTextReader reader) + private static void ProcessCurrentPermissions(InventoryItemBase item, XmlReader reader) { item.CurrentPermissions = (uint)reader.ReadElementContentAsInt("CurrentPermissions", String.Empty); } - private static void ProcessEveryOnePermissions(InventoryItemBase item, XmlTextReader reader) + private static void ProcessEveryOnePermissions(InventoryItemBase item, XmlReader reader) { item.EveryOnePermissions = (uint)reader.ReadElementContentAsInt("EveryOnePermissions", String.Empty); } - private static void ProcessNextPermissions(InventoryItemBase item, XmlTextReader reader) + private static void ProcessNextPermissions(InventoryItemBase item, XmlReader reader) { item.NextPermissions = (uint)reader.ReadElementContentAsInt("NextPermissions", String.Empty); } - private static void ProcessFlags(InventoryItemBase item, XmlTextReader reader) + private static void ProcessFlags(InventoryItemBase item, XmlReader reader) { item.Flags = (uint)reader.ReadElementContentAsInt("Flags", String.Empty); } - private static void ProcessGroupID(InventoryItemBase item, XmlTextReader reader) + private static void ProcessGroupID(InventoryItemBase item, XmlReader reader) { item.GroupID = Util.ReadUUID(reader, "GroupID"); } - private static void ProcessGroupOwned(InventoryItemBase item, XmlTextReader reader) + private static void ProcessGroupOwned(InventoryItemBase item, XmlReader reader) { item.GroupOwned = Util.ReadBoolean(reader); } - private static void ProcessCreatorData(InventoryItemBase item, XmlTextReader reader) + private static void ProcessCreatorData(InventoryItemBase item, XmlReader reader) { item.CreatorData = reader.ReadElementContentAsString("CreatorData", String.Empty); } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 2d0178e4b8..2c38571147 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -2605,7 +2605,7 @@ namespace OpenSim.Framework } #region Xml Serialization Utilities - public static bool ReadBoolean(XmlTextReader reader) + public static bool ReadBoolean(XmlReader reader) { // AuroraSim uses "int" for some fields that are boolean in OpenSim, e.g. "PassCollisions". Don't fail because of this. reader.ReadStartElement(); @@ -2616,7 +2616,7 @@ namespace OpenSim.Framework return result; } - public static UUID ReadUUID(XmlTextReader reader, string name) + public static UUID ReadUUID(XmlReader reader, string name) { UUID id; string idStr; @@ -2635,7 +2635,7 @@ namespace OpenSim.Framework return id; } - public static Vector3 ReadVector(XmlTextReader reader, string name) + public static Vector3 ReadVector(XmlReader reader, string name) { Vector3 vec; @@ -2648,7 +2648,7 @@ namespace OpenSim.Framework return vec; } - public static Quaternion ReadQuaternion(XmlTextReader reader, string name) + public static Quaternion ReadQuaternion(XmlReader reader, string name) { Quaternion quat = new Quaternion(); @@ -2677,7 +2677,7 @@ namespace OpenSim.Framework return quat; } - public static T ReadEnum(XmlTextReader reader, string name) + public static T ReadEnum(XmlReader reader, string name) { string value = reader.ReadElementContentAsString(name, String.Empty); // !!!!! to deal with flags without commas diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index 94cd9cd9dd..a5bb1a73a2 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs @@ -624,23 +624,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests TestHelpers.InMethod(); TestHelpers.EnableLogging(); - // We need to do this to get rid of whitespace between elements. - // TODO: Ultimately OpenSimulator xml parser should be set to ignore this but this means a bit of - // rejigging to replace old new XmlTextReader() with the post .NET 2.0 XmlReader.Create() calls - XmlDocument xdoc = new XmlDocument(); - xdoc.LoadXml(ObjectWithOtherPartsXml); - - StringBuilder sb = new StringBuilder(); - using (StringWriter sw = new StringWriter(sb)) - { - using (XmlTextWriter xtw = new XmlTextWriter(sw)) - { -// xtw.Formatting = Formatting.Indented; - xdoc.WriteTo(xtw); - } - } - - SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(sb.ToString()); + SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithOtherPartsXml); SceneObjectPart[] parts = so.Parts; Assert.AreEqual(3, so.Parts.Length); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index cbb4fe771a..3489873836 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2214,49 +2214,52 @@ namespace OpenSim.Region.Framework.Scenes try { - using (XmlTextReader reader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) + using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) { - reader.Read(); - bool isSingleObject = reader.Name != "CoalescedObject"; - - if (isSingleObject || isAttachment) + using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) { - SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(reader); - objlist.Add(g); - veclist.Add(Vector3.Zero); - bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); - return true; - } - else - { - XmlDocument doc = new XmlDocument(); - doc.LoadXml(xmlData); - XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); - XmlElement coll = (XmlElement)e; - float bx = Convert.ToSingle(coll.GetAttribute("x")); - float by = Convert.ToSingle(coll.GetAttribute("y")); - float bz = Convert.ToSingle(coll.GetAttribute("z")); - bbox = new Vector3(bx, by, bz); - offsetHeight = 0; + reader.Read(); + bool isSingleObject = reader.Name != "CoalescedObject"; - XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); - foreach (XmlNode n in groups) + if (isSingleObject || isAttachment) { - SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); + SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(reader); objlist.Add(g); - - XmlElement el = (XmlElement)n; - string rawX = el.GetAttribute("offsetx"); - string rawY = el.GetAttribute("offsety"); - string rawZ = el.GetAttribute("offsetz"); - - float x = Convert.ToSingle(rawX); - float y = Convert.ToSingle(rawY); - float z = Convert.ToSingle(rawZ); - veclist.Add(new Vector3(x, y, z)); + veclist.Add(Vector3.Zero); + bbox = g.GetAxisAlignedBoundingBox(out offsetHeight); + return true; } + else + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlData); + XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); + XmlElement coll = (XmlElement)e; + float bx = Convert.ToSingle(coll.GetAttribute("x")); + float by = Convert.ToSingle(coll.GetAttribute("y")); + float bz = Convert.ToSingle(coll.GetAttribute("z")); + bbox = new Vector3(bx, by, bz); + offsetHeight = 0; - return false; + XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); + foreach (XmlNode n in groups) + { + SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); + objlist.Add(g); + + XmlElement el = (XmlElement)n; + string rawX = el.GetAttribute("offsetx"); + string rawY = el.GetAttribute("offsety"); + string rawZ = el.GetAttribute("offsetz"); + + float x = Convert.ToSingle(rawX); + float y = Convert.ToSingle(rawY); + float z = Convert.ToSingle(rawZ); + veclist.Add(new Vector3(x, y, z)); + } + + return false; + } } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c95d2076a4..e37bbd81b6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -902,7 +902,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public void LoadScriptState(XmlTextReader reader) + public void LoadScriptState(XmlReader reader) { // m_log.DebugFormat("[SCENE OBJECT GROUP]: Looking for script state for {0} in {1}", Name); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 31fc26ebbb..05e3ee906e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2044,7 +2044,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public static SceneObjectPart FromXml(XmlTextReader xmlReader) + public static SceneObjectPart FromXml(XmlReader xmlReader) { SceneObjectPart part = SceneObjectSerializer.Xml2ToSOP(xmlReader); diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 8f99dc6f8e..3899b99cbc 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -59,8 +59,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// The scene object deserialized. Null on failure. public static SceneObjectGroup FromOriginalXmlFormat(string xmlData) { - using (XmlTextReader reader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) - return FromOriginalXmlFormat(reader); + using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) + using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) + return FromOriginalXmlFormat(reader); } /// @@ -68,7 +69,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// /// /// The scene object deserialized. Null on failure. - public static SceneObjectGroup FromOriginalXmlFormat(XmlTextReader reader) + public static SceneObjectGroup FromOriginalXmlFormat(XmlReader reader) { //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); //int time = System.Environment.TickCount; @@ -370,14 +371,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization #region manual serialization - private static Dictionary> m_SOPXmlProcessors - = new Dictionary>(); + private static Dictionary> m_SOPXmlProcessors + = new Dictionary>(); - private static Dictionary> m_TaskInventoryXmlProcessors - = new Dictionary>(); + private static Dictionary> m_TaskInventoryXmlProcessors + = new Dictionary>(); - private static Dictionary> m_ShapeXmlProcessors - = new Dictionary>(); + private static Dictionary> m_ShapeXmlProcessors + = new Dictionary>(); static SceneObjectSerializer() { @@ -533,112 +534,112 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } #region SOPXmlProcessors - private static void ProcessAllowedDrop(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessAllowedDrop(SceneObjectPart obj, XmlReader reader) { obj.AllowedDrop = Util.ReadBoolean(reader); } - private static void ProcessCreatorID(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessCreatorID(SceneObjectPart obj, XmlReader reader) { obj.CreatorID = Util.ReadUUID(reader, "CreatorID"); } - private static void ProcessCreatorData(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessCreatorData(SceneObjectPart obj, XmlReader reader) { obj.CreatorData = reader.ReadElementContentAsString("CreatorData", String.Empty); } - private static void ProcessFolderID(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessFolderID(SceneObjectPart obj, XmlReader reader) { obj.FolderID = Util.ReadUUID(reader, "FolderID"); } - private static void ProcessInventorySerial(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessInventorySerial(SceneObjectPart obj, XmlReader reader) { obj.InventorySerial = (uint)reader.ReadElementContentAsInt("InventorySerial", String.Empty); } - private static void ProcessTaskInventory(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessTaskInventory(SceneObjectPart obj, XmlReader reader) { obj.TaskInventory = ReadTaskInventory(reader, "TaskInventory"); } - private static void ProcessUUID(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessUUID(SceneObjectPart obj, XmlReader reader) { obj.UUID = Util.ReadUUID(reader, "UUID"); } - private static void ProcessLocalId(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessLocalId(SceneObjectPart obj, XmlReader reader) { obj.LocalId = (uint)reader.ReadElementContentAsLong("LocalId", String.Empty); } - private static void ProcessName(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessName(SceneObjectPart obj, XmlReader reader) { obj.Name = reader.ReadElementString("Name"); } - private static void ProcessMaterial(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessMaterial(SceneObjectPart obj, XmlReader reader) { obj.Material = (byte)reader.ReadElementContentAsInt("Material", String.Empty); } - private static void ProcessPassTouches(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPassTouches(SceneObjectPart obj, XmlReader reader) { obj.PassTouches = Util.ReadBoolean(reader); } - private static void ProcessPassCollisions(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPassCollisions(SceneObjectPart obj, XmlReader reader) { obj.PassCollisions = Util.ReadBoolean(reader); } - private static void ProcessRegionHandle(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessRegionHandle(SceneObjectPart obj, XmlReader reader) { obj.RegionHandle = (ulong)reader.ReadElementContentAsLong("RegionHandle", String.Empty); } - private static void ProcessScriptAccessPin(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessScriptAccessPin(SceneObjectPart obj, XmlReader reader) { obj.ScriptAccessPin = reader.ReadElementContentAsInt("ScriptAccessPin", String.Empty); } - private static void ProcessGroupPosition(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessGroupPosition(SceneObjectPart obj, XmlReader reader) { obj.GroupPosition = Util.ReadVector(reader, "GroupPosition"); } - private static void ProcessOffsetPosition(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessOffsetPosition(SceneObjectPart obj, XmlReader reader) { obj.OffsetPosition = Util.ReadVector(reader, "OffsetPosition"); ; } - private static void ProcessRotationOffset(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessRotationOffset(SceneObjectPart obj, XmlReader reader) { obj.RotationOffset = Util.ReadQuaternion(reader, "RotationOffset"); } - private static void ProcessVelocity(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessVelocity(SceneObjectPart obj, XmlReader reader) { obj.Velocity = Util.ReadVector(reader, "Velocity"); } - private static void ProcessAngularVelocity(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessAngularVelocity(SceneObjectPart obj, XmlReader reader) { obj.AngularVelocity = Util.ReadVector(reader, "AngularVelocity"); } - private static void ProcessAcceleration(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessAcceleration(SceneObjectPart obj, XmlReader reader) { obj.Acceleration = Util.ReadVector(reader, "Acceleration"); } - private static void ProcessDescription(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessDescription(SceneObjectPart obj, XmlReader reader) { obj.Description = reader.ReadElementString("Description"); } - private static void ProcessColor(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessColor(SceneObjectPart obj, XmlReader reader) { reader.ReadStartElement("Color"); if (reader.Name == "R") @@ -652,57 +653,57 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } - private static void ProcessText(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessText(SceneObjectPart obj, XmlReader reader) { obj.Text = reader.ReadElementString("Text", String.Empty); } - private static void ProcessSitName(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessSitName(SceneObjectPart obj, XmlReader reader) { obj.SitName = reader.ReadElementString("SitName", String.Empty); } - private static void ProcessTouchName(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessTouchName(SceneObjectPart obj, XmlReader reader) { obj.TouchName = reader.ReadElementString("TouchName", String.Empty); } - private static void ProcessLinkNum(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessLinkNum(SceneObjectPart obj, XmlReader reader) { obj.LinkNum = reader.ReadElementContentAsInt("LinkNum", String.Empty); } - private static void ProcessClickAction(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessClickAction(SceneObjectPart obj, XmlReader reader) { obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); } - private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlReader reader) { obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty); } - private static void ProcessDensity(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessDensity(SceneObjectPart obj, XmlReader reader) { obj.Density = reader.ReadElementContentAsFloat("Density", String.Empty); } - private static void ProcessFriction(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessFriction(SceneObjectPart obj, XmlReader reader) { obj.Friction = reader.ReadElementContentAsFloat("Friction", String.Empty); } - private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessBounce(SceneObjectPart obj, XmlReader reader) { obj.Restitution = reader.ReadElementContentAsFloat("Bounce", String.Empty); } - private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessGravityModifier(SceneObjectPart obj, XmlReader reader) { obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty); } - private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessShape(SceneObjectPart obj, XmlReader reader) { List errorNodeNames; obj.Shape = ReadShape(reader, "Shape", out errorNodeNames); @@ -715,163 +716,163 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } - private static void ProcessScale(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessScale(SceneObjectPart obj, XmlReader reader) { obj.Scale = Util.ReadVector(reader, "Scale"); } - private static void ProcessSitTargetOrientation(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessSitTargetOrientation(SceneObjectPart obj, XmlReader reader) { obj.SitTargetOrientation = Util.ReadQuaternion(reader, "SitTargetOrientation"); } - private static void ProcessSitTargetPosition(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessSitTargetPosition(SceneObjectPart obj, XmlReader reader) { obj.SitTargetPosition = Util.ReadVector(reader, "SitTargetPosition"); } - private static void ProcessSitTargetPositionLL(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessSitTargetPositionLL(SceneObjectPart obj, XmlReader reader) { obj.SitTargetPositionLL = Util.ReadVector(reader, "SitTargetPositionLL"); } - private static void ProcessSitTargetOrientationLL(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessSitTargetOrientationLL(SceneObjectPart obj, XmlReader reader) { obj.SitTargetOrientationLL = Util.ReadQuaternion(reader, "SitTargetOrientationLL"); } - private static void ProcessParentID(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessParentID(SceneObjectPart obj, XmlReader reader) { string str = reader.ReadElementContentAsString("ParentID", String.Empty); obj.ParentID = Convert.ToUInt32(str); } - private static void ProcessCreationDate(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessCreationDate(SceneObjectPart obj, XmlReader reader) { obj.CreationDate = reader.ReadElementContentAsInt("CreationDate", String.Empty); } - private static void ProcessCategory(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessCategory(SceneObjectPart obj, XmlReader reader) { obj.Category = (uint)reader.ReadElementContentAsInt("Category", String.Empty); } - private static void ProcessSalePrice(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessSalePrice(SceneObjectPart obj, XmlReader reader) { obj.SalePrice = reader.ReadElementContentAsInt("SalePrice", String.Empty); } - private static void ProcessObjectSaleType(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessObjectSaleType(SceneObjectPart obj, XmlReader reader) { obj.ObjectSaleType = (byte)reader.ReadElementContentAsInt("ObjectSaleType", String.Empty); } - private static void ProcessOwnershipCost(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessOwnershipCost(SceneObjectPart obj, XmlReader reader) { obj.OwnershipCost = reader.ReadElementContentAsInt("OwnershipCost", String.Empty); } - private static void ProcessGroupID(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessGroupID(SceneObjectPart obj, XmlReader reader) { obj.GroupID = Util.ReadUUID(reader, "GroupID"); } - private static void ProcessOwnerID(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessOwnerID(SceneObjectPart obj, XmlReader reader) { obj.OwnerID = Util.ReadUUID(reader, "OwnerID"); } - private static void ProcessLastOwnerID(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessLastOwnerID(SceneObjectPart obj, XmlReader reader) { obj.LastOwnerID = Util.ReadUUID(reader, "LastOwnerID"); } - private static void ProcessBaseMask(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessBaseMask(SceneObjectPart obj, XmlReader reader) { obj.BaseMask = (uint)reader.ReadElementContentAsInt("BaseMask", String.Empty); } - private static void ProcessOwnerMask(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessOwnerMask(SceneObjectPart obj, XmlReader reader) { obj.OwnerMask = (uint)reader.ReadElementContentAsInt("OwnerMask", String.Empty); } - private static void ProcessGroupMask(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessGroupMask(SceneObjectPart obj, XmlReader reader) { obj.GroupMask = (uint)reader.ReadElementContentAsInt("GroupMask", String.Empty); } - private static void ProcessEveryoneMask(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessEveryoneMask(SceneObjectPart obj, XmlReader reader) { obj.EveryoneMask = (uint)reader.ReadElementContentAsInt("EveryoneMask", String.Empty); } - private static void ProcessNextOwnerMask(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessNextOwnerMask(SceneObjectPart obj, XmlReader reader) { obj.NextOwnerMask = (uint)reader.ReadElementContentAsInt("NextOwnerMask", String.Empty); } - private static void ProcessFlags(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessFlags(SceneObjectPart obj, XmlReader reader) { obj.Flags = Util.ReadEnum(reader, "Flags"); } - private static void ProcessCollisionSound(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessCollisionSound(SceneObjectPart obj, XmlReader reader) { obj.CollisionSound = Util.ReadUUID(reader, "CollisionSound"); } - private static void ProcessCollisionSoundVolume(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessCollisionSoundVolume(SceneObjectPart obj, XmlReader reader) { obj.CollisionSoundVolume = reader.ReadElementContentAsFloat("CollisionSoundVolume", String.Empty); } - private static void ProcessMediaUrl(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessMediaUrl(SceneObjectPart obj, XmlReader reader) { obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); } - private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessAttachedPos(SceneObjectPart obj, XmlReader reader) { obj.AttachedPos = Util.ReadVector(reader, "AttachedPos"); } - private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessDynAttrs(SceneObjectPart obj, XmlReader reader) { obj.DynAttrs.ReadXml(reader); } - private static void ProcessTextureAnimation(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessTextureAnimation(SceneObjectPart obj, XmlReader reader) { obj.TextureAnimation = Convert.FromBase64String(reader.ReadElementContentAsString("TextureAnimation", String.Empty)); } - private static void ProcessParticleSystem(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessParticleSystem(SceneObjectPart obj, XmlReader reader) { obj.ParticleSystem = Convert.FromBase64String(reader.ReadElementContentAsString("ParticleSystem", String.Empty)); } - private static void ProcessPayPrice0(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPayPrice0(SceneObjectPart obj, XmlReader reader) { obj.PayPrice[0] = (int)reader.ReadElementContentAsInt("PayPrice0", String.Empty); } - private static void ProcessPayPrice1(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPayPrice1(SceneObjectPart obj, XmlReader reader) { obj.PayPrice[1] = (int)reader.ReadElementContentAsInt("PayPrice1", String.Empty); } - private static void ProcessPayPrice2(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPayPrice2(SceneObjectPart obj, XmlReader reader) { obj.PayPrice[2] = (int)reader.ReadElementContentAsInt("PayPrice2", String.Empty); } - private static void ProcessPayPrice3(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPayPrice3(SceneObjectPart obj, XmlReader reader) { obj.PayPrice[3] = (int)reader.ReadElementContentAsInt("PayPrice3", String.Empty); } - private static void ProcessPayPrice4(SceneObjectPart obj, XmlTextReader reader) + private static void ProcessPayPrice4(SceneObjectPart obj, XmlReader reader) { obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); } @@ -879,122 +880,122 @@ namespace OpenSim.Region.Framework.Scenes.Serialization #endregion #region TaskInventoryXmlProcessors - private static void ProcessTIAssetID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIAssetID(TaskInventoryItem item, XmlReader reader) { item.AssetID = Util.ReadUUID(reader, "AssetID"); } - private static void ProcessTIBasePermissions(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIBasePermissions(TaskInventoryItem item, XmlReader reader) { item.BasePermissions = (uint)reader.ReadElementContentAsInt("BasePermissions", String.Empty); } - private static void ProcessTICreationDate(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTICreationDate(TaskInventoryItem item, XmlReader reader) { item.CreationDate = (uint)reader.ReadElementContentAsInt("CreationDate", String.Empty); } - private static void ProcessTICreatorID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTICreatorID(TaskInventoryItem item, XmlReader reader) { item.CreatorID = Util.ReadUUID(reader, "CreatorID"); } - private static void ProcessTICreatorData(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTICreatorData(TaskInventoryItem item, XmlReader reader) { item.CreatorData = reader.ReadElementContentAsString("CreatorData", String.Empty); } - private static void ProcessTIDescription(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIDescription(TaskInventoryItem item, XmlReader reader) { item.Description = reader.ReadElementContentAsString("Description", String.Empty); } - private static void ProcessTIEveryonePermissions(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIEveryonePermissions(TaskInventoryItem item, XmlReader reader) { item.EveryonePermissions = (uint)reader.ReadElementContentAsInt("EveryonePermissions", String.Empty); } - private static void ProcessTIFlags(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIFlags(TaskInventoryItem item, XmlReader reader) { item.Flags = (uint)reader.ReadElementContentAsInt("Flags", String.Empty); } - private static void ProcessTIGroupID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIGroupID(TaskInventoryItem item, XmlReader reader) { item.GroupID = Util.ReadUUID(reader, "GroupID"); } - private static void ProcessTIGroupPermissions(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIGroupPermissions(TaskInventoryItem item, XmlReader reader) { item.GroupPermissions = (uint)reader.ReadElementContentAsInt("GroupPermissions", String.Empty); } - private static void ProcessTIInvType(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIInvType(TaskInventoryItem item, XmlReader reader) { item.InvType = reader.ReadElementContentAsInt("InvType", String.Empty); } - private static void ProcessTIItemID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIItemID(TaskInventoryItem item, XmlReader reader) { item.ItemID = Util.ReadUUID(reader, "ItemID"); } - private static void ProcessTIOldItemID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIOldItemID(TaskInventoryItem item, XmlReader reader) { item.OldItemID = Util.ReadUUID(reader, "OldItemID"); } - private static void ProcessTILastOwnerID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTILastOwnerID(TaskInventoryItem item, XmlReader reader) { item.LastOwnerID = Util.ReadUUID(reader, "LastOwnerID"); } - private static void ProcessTIName(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIName(TaskInventoryItem item, XmlReader reader) { item.Name = reader.ReadElementContentAsString("Name", String.Empty); } - private static void ProcessTINextPermissions(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTINextPermissions(TaskInventoryItem item, XmlReader reader) { item.NextPermissions = (uint)reader.ReadElementContentAsInt("NextPermissions", String.Empty); } - private static void ProcessTIOwnerID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIOwnerID(TaskInventoryItem item, XmlReader reader) { item.OwnerID = Util.ReadUUID(reader, "OwnerID"); } - private static void ProcessTICurrentPermissions(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTICurrentPermissions(TaskInventoryItem item, XmlReader reader) { item.CurrentPermissions = (uint)reader.ReadElementContentAsInt("CurrentPermissions", String.Empty); } - private static void ProcessTIParentID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIParentID(TaskInventoryItem item, XmlReader reader) { item.ParentID = Util.ReadUUID(reader, "ParentID"); } - private static void ProcessTIParentPartID(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIParentPartID(TaskInventoryItem item, XmlReader reader) { item.ParentPartID = Util.ReadUUID(reader, "ParentPartID"); } - private static void ProcessTIPermsGranter(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIPermsGranter(TaskInventoryItem item, XmlReader reader) { item.PermsGranter = Util.ReadUUID(reader, "PermsGranter"); } - private static void ProcessTIPermsMask(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIPermsMask(TaskInventoryItem item, XmlReader reader) { item.PermsMask = reader.ReadElementContentAsInt("PermsMask", String.Empty); } - private static void ProcessTIType(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIType(TaskInventoryItem item, XmlReader reader) { item.Type = reader.ReadElementContentAsInt("Type", String.Empty); } - private static void ProcessTIOwnerChanged(TaskInventoryItem item, XmlTextReader reader) + private static void ProcessTIOwnerChanged(TaskInventoryItem item, XmlReader reader) { item.OwnerChanged = Util.ReadBoolean(reader); } @@ -1002,243 +1003,243 @@ namespace OpenSim.Region.Framework.Scenes.Serialization #endregion #region ShapeXmlProcessors - private static void ProcessShpProfileCurve(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpProfileCurve(PrimitiveBaseShape shp, XmlReader reader) { shp.ProfileCurve = (byte)reader.ReadElementContentAsInt("ProfileCurve", String.Empty); } - private static void ProcessShpTextureEntry(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpTextureEntry(PrimitiveBaseShape shp, XmlReader reader) { byte[] teData = Convert.FromBase64String(reader.ReadElementString("TextureEntry")); shp.Textures = new Primitive.TextureEntry(teData, 0, teData.Length); } - private static void ProcessShpExtraParams(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpExtraParams(PrimitiveBaseShape shp, XmlReader reader) { shp.ExtraParams = Convert.FromBase64String(reader.ReadElementString("ExtraParams")); } - private static void ProcessShpPathBegin(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathBegin(PrimitiveBaseShape shp, XmlReader reader) { shp.PathBegin = (ushort)reader.ReadElementContentAsInt("PathBegin", String.Empty); } - private static void ProcessShpPathCurve(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathCurve(PrimitiveBaseShape shp, XmlReader reader) { shp.PathCurve = (byte)reader.ReadElementContentAsInt("PathCurve", String.Empty); } - private static void ProcessShpPathEnd(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathEnd(PrimitiveBaseShape shp, XmlReader reader) { shp.PathEnd = (ushort)reader.ReadElementContentAsInt("PathEnd", String.Empty); } - private static void ProcessShpPathRadiusOffset(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathRadiusOffset(PrimitiveBaseShape shp, XmlReader reader) { shp.PathRadiusOffset = (sbyte)reader.ReadElementContentAsInt("PathRadiusOffset", String.Empty); } - private static void ProcessShpPathRevolutions(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathRevolutions(PrimitiveBaseShape shp, XmlReader reader) { shp.PathRevolutions = (byte)reader.ReadElementContentAsInt("PathRevolutions", String.Empty); } - private static void ProcessShpPathScaleX(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathScaleX(PrimitiveBaseShape shp, XmlReader reader) { shp.PathScaleX = (byte)reader.ReadElementContentAsInt("PathScaleX", String.Empty); } - private static void ProcessShpPathScaleY(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathScaleY(PrimitiveBaseShape shp, XmlReader reader) { shp.PathScaleY = (byte)reader.ReadElementContentAsInt("PathScaleY", String.Empty); } - private static void ProcessShpPathShearX(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathShearX(PrimitiveBaseShape shp, XmlReader reader) { shp.PathShearX = (byte)reader.ReadElementContentAsInt("PathShearX", String.Empty); } - private static void ProcessShpPathShearY(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathShearY(PrimitiveBaseShape shp, XmlReader reader) { shp.PathShearY = (byte)reader.ReadElementContentAsInt("PathShearY", String.Empty); } - private static void ProcessShpPathSkew(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathSkew(PrimitiveBaseShape shp, XmlReader reader) { shp.PathSkew = (sbyte)reader.ReadElementContentAsInt("PathSkew", String.Empty); } - private static void ProcessShpPathTaperX(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathTaperX(PrimitiveBaseShape shp, XmlReader reader) { shp.PathTaperX = (sbyte)reader.ReadElementContentAsInt("PathTaperX", String.Empty); } - private static void ProcessShpPathTaperY(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathTaperY(PrimitiveBaseShape shp, XmlReader reader) { shp.PathTaperY = (sbyte)reader.ReadElementContentAsInt("PathTaperY", String.Empty); } - private static void ProcessShpPathTwist(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathTwist(PrimitiveBaseShape shp, XmlReader reader) { shp.PathTwist = (sbyte)reader.ReadElementContentAsInt("PathTwist", String.Empty); } - private static void ProcessShpPathTwistBegin(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPathTwistBegin(PrimitiveBaseShape shp, XmlReader reader) { shp.PathTwistBegin = (sbyte)reader.ReadElementContentAsInt("PathTwistBegin", String.Empty); } - private static void ProcessShpPCode(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpPCode(PrimitiveBaseShape shp, XmlReader reader) { shp.PCode = (byte)reader.ReadElementContentAsInt("PCode", String.Empty); } - private static void ProcessShpProfileBegin(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpProfileBegin(PrimitiveBaseShape shp, XmlReader reader) { shp.ProfileBegin = (ushort)reader.ReadElementContentAsInt("ProfileBegin", String.Empty); } - private static void ProcessShpProfileEnd(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpProfileEnd(PrimitiveBaseShape shp, XmlReader reader) { shp.ProfileEnd = (ushort)reader.ReadElementContentAsInt("ProfileEnd", String.Empty); } - private static void ProcessShpProfileHollow(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpProfileHollow(PrimitiveBaseShape shp, XmlReader reader) { shp.ProfileHollow = (ushort)reader.ReadElementContentAsInt("ProfileHollow", String.Empty); } - private static void ProcessShpScale(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpScale(PrimitiveBaseShape shp, XmlReader reader) { shp.Scale = Util.ReadVector(reader, "Scale"); } - private static void ProcessShpState(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpState(PrimitiveBaseShape shp, XmlReader reader) { shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); } - private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlReader reader) { shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty); } - private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlReader reader) { shp.ProfileShape = Util.ReadEnum(reader, "ProfileShape"); } - private static void ProcessShpHollowShape(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpHollowShape(PrimitiveBaseShape shp, XmlReader reader) { shp.HollowShape = Util.ReadEnum(reader, "HollowShape"); } - private static void ProcessShpSculptTexture(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpSculptTexture(PrimitiveBaseShape shp, XmlReader reader) { shp.SculptTexture = Util.ReadUUID(reader, "SculptTexture"); } - private static void ProcessShpSculptType(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpSculptType(PrimitiveBaseShape shp, XmlReader reader) { shp.SculptType = (byte)reader.ReadElementContentAsInt("SculptType", String.Empty); } - private static void ProcessShpFlexiSoftness(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiSoftness(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiSoftness = reader.ReadElementContentAsInt("FlexiSoftness", String.Empty); } - private static void ProcessShpFlexiTension(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiTension(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiTension = reader.ReadElementContentAsFloat("FlexiTension", String.Empty); } - private static void ProcessShpFlexiDrag(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiDrag(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiDrag = reader.ReadElementContentAsFloat("FlexiDrag", String.Empty); } - private static void ProcessShpFlexiGravity(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiGravity(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiGravity = reader.ReadElementContentAsFloat("FlexiGravity", String.Empty); } - private static void ProcessShpFlexiWind(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiWind(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiWind = reader.ReadElementContentAsFloat("FlexiWind", String.Empty); } - private static void ProcessShpFlexiForceX(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiForceX(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiForceX = reader.ReadElementContentAsFloat("FlexiForceX", String.Empty); } - private static void ProcessShpFlexiForceY(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiForceY(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiForceY = reader.ReadElementContentAsFloat("FlexiForceY", String.Empty); } - private static void ProcessShpFlexiForceZ(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiForceZ(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiForceZ = reader.ReadElementContentAsFloat("FlexiForceZ", String.Empty); } - private static void ProcessShpLightColorR(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightColorR(PrimitiveBaseShape shp, XmlReader reader) { shp.LightColorR = reader.ReadElementContentAsFloat("LightColorR", String.Empty); } - private static void ProcessShpLightColorG(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightColorG(PrimitiveBaseShape shp, XmlReader reader) { shp.LightColorG = reader.ReadElementContentAsFloat("LightColorG", String.Empty); } - private static void ProcessShpLightColorB(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightColorB(PrimitiveBaseShape shp, XmlReader reader) { shp.LightColorB = reader.ReadElementContentAsFloat("LightColorB", String.Empty); } - private static void ProcessShpLightColorA(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightColorA(PrimitiveBaseShape shp, XmlReader reader) { shp.LightColorA = reader.ReadElementContentAsFloat("LightColorA", String.Empty); } - private static void ProcessShpLightRadius(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightRadius(PrimitiveBaseShape shp, XmlReader reader) { shp.LightRadius = reader.ReadElementContentAsFloat("LightRadius", String.Empty); } - private static void ProcessShpLightCutoff(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightCutoff(PrimitiveBaseShape shp, XmlReader reader) { shp.LightCutoff = reader.ReadElementContentAsFloat("LightCutoff", String.Empty); } - private static void ProcessShpLightFalloff(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightFalloff(PrimitiveBaseShape shp, XmlReader reader) { shp.LightFalloff = reader.ReadElementContentAsFloat("LightFalloff", String.Empty); } - private static void ProcessShpLightIntensity(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightIntensity(PrimitiveBaseShape shp, XmlReader reader) { shp.LightIntensity = reader.ReadElementContentAsFloat("LightIntensity", String.Empty); } - private static void ProcessShpFlexiEntry(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpFlexiEntry(PrimitiveBaseShape shp, XmlReader reader) { shp.FlexiEntry = Util.ReadBoolean(reader); } - private static void ProcessShpLightEntry(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpLightEntry(PrimitiveBaseShape shp, XmlReader reader) { shp.LightEntry = Util.ReadBoolean(reader); } - private static void ProcessShpSculptEntry(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpSculptEntry(PrimitiveBaseShape shp, XmlReader reader) { shp.SculptEntry = Util.ReadBoolean(reader); } - private static void ProcessShpMedia(PrimitiveBaseShape shp, XmlTextReader reader) + private static void ProcessShpMedia(PrimitiveBaseShape shp, XmlReader reader) { string value = reader.ReadElementContentAsString("Media", String.Empty); shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); @@ -1590,7 +1591,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } - public static SceneObjectPart Xml2ToSOP(XmlTextReader reader) + public static SceneObjectPart Xml2ToSOP(XmlReader reader) { SceneObjectPart obj = new SceneObjectPart(); @@ -1611,7 +1612,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization return obj; } - public static TaskInventoryDictionary ReadTaskInventory(XmlTextReader reader, string name) + public static TaskInventoryDictionary ReadTaskInventory(XmlReader reader, string name) { TaskInventoryDictionary tinv = new TaskInventoryDictionary(); @@ -1652,7 +1653,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// The name of the xml element containing the shape /// a list containing the failing node names. If no failures then null. /// The shape parsed - public static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out List errorNodeNames) + public static PrimitiveBaseShape ReadShape(XmlReader reader, string name, out List errorNodeNames) { List internalErrorNodeNames = null; From 099212167b2b3d5f8bdf529d24a6c47536716706 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 29 Aug 2014 23:40:21 +0100 Subject: [PATCH 10/15] Implement STATUS_BLOCK_GRAB_OBJECT in llSetStatus()/llGetStatus() and correct effect of STATUS_BLOCK_GRAB As per http://wiki.secondlife.com/wiki/LlSetStatus Setting STATUS_BLOCK_GRAB_OBJECT prevents or allows move of a physical linkset by grab on any prim. Setting STATUS_BLOCK_GRAB prevents or allows move of a physical linkset by grab on a particular prim. Previously, setting STATUS_BLOCK_GRAB would prevent drag via all prims of the linkset. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 3 ++- .../Framework/Scenes/SceneObjectGroup.cs | 16 ++++++++++++++-- .../Region/Framework/Scenes/SceneObjectPart.cs | 18 +----------------- .../Shared/Api/Implementation/LSL_Api.cs | 18 ++++++++---------- .../Shared/Api/Runtime/LSL_Constants.cs | 1 + 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 3678c7e5c4..51f50d9ea8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1446,8 +1446,9 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) { - group.GrabMovement(offset, pos, remoteClient); + group.GrabMovement(objectID, offset, pos, remoteClient); } + // This is outside the above permissions condition // so that if the object is locked the client moving the object // get's it's position on the simulator even if it was the same as before diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index e37bbd81b6..2aeccd8ab3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -827,6 +827,12 @@ namespace OpenSim.Region.Framework.Scenes /// public UUID FromFolderID { get; set; } + /// + /// If true then grabs are blocked no matter what the individual part BlockGrab setting. + /// + /// true if block grab override; otherwise, false. + public bool BlockGrabOverride { get; set; } + /// /// IDs of all avatars sat on this scene object. /// @@ -2610,20 +2616,26 @@ namespace OpenSim.Region.Framework.Scenes /// If object is physical, apply force to move it around /// If object is not physical, just put it at the resulting location /// + /// Part ID to check for grab /// Always seems to be 0,0,0, so ignoring /// New position. We do the math here to turn it into a force /// - public void GrabMovement(Vector3 offset, Vector3 pos, IClientAPI remoteClient) + public void GrabMovement(UUID partID, Vector3 offset, Vector3 pos, IClientAPI remoteClient) { if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) { + SceneObjectPart part = GetPart(partID); + + if (part == null) + return; + PhysicsActor pa = m_rootPart.PhysActor; if (pa != null) { if (pa.IsPhysical) { - if (!m_rootPart.BlockGrab) + if (!BlockGrabOverride && !part.BlockGrab) { Vector3 llmoveforce = pos - AbsolutePosition; Vector3 grabforce = llmoveforce; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 05e3ee906e..8785ca97d8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -186,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes public bool RETURN_AT_EDGE; - public bool BlockGrab; + public bool BlockGrab { get; set; } public bool StatusSandbox; @@ -2079,22 +2079,6 @@ namespace OpenSim.Region.Framework.Scenes ParentGroup.RootPart.RETURN_AT_EDGE = p; } - public bool GetBlockGrab() - { - if (ParentGroup.IsDeleted) - return false; - - return ParentGroup.RootPart.BlockGrab; - } - - public void SetBlockGrab(bool p) - { - if (ParentGroup.IsDeleted) - return; - - ParentGroup.RootPart.BlockGrab = p; - } - public void SetStatusSandbox(bool p) { if (ParentGroup.IsDeleted) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 50e4804ef0..5aef892eb9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1377,12 +1377,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) - { - if (value != 0) - m_host.SetBlockGrab(true); - else - m_host.SetBlockGrab(false); - } + m_host.BlockGrab = value != 0; + + if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) + m_host.ParentGroup.BlockGrabOverride = value != 0; if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) { @@ -1443,10 +1441,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return 0; case ScriptBaseClass.STATUS_BLOCK_GRAB: - if (m_host.GetBlockGrab()) - return 1; - else - return 0; + return m_host.BlockGrab ? 1 : 0; + + case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT: + return m_host.ParentGroup.BlockGrabOverride ? 1 : 0; case ScriptBaseClass.STATUS_DIE_AT_EDGE: if (m_host.GetDieAtEdge()) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 7d80dcbf27..a96cd16355 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -48,6 +48,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int STATUS_DIE_AT_EDGE = 128; public const int STATUS_RETURN_AT_EDGE = 256; public const int STATUS_CAST_SHADOWS = 512; + public const int STATUS_BLOCK_GRAB_OBJECT = 1024; public const int AGENT = 1; public const int AGENT_BY_LEGACY_NAME = 1; From a02dae566ce510e7f43c6324996e70442cba3f46 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 30 Aug 2014 00:26:18 +0100 Subject: [PATCH 11/15] Fix issue where moving a seated avatar would not adjust their subsequent stand position. Addresses http://opensimulator.org/mantis/view.php?id=7299 --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index ebbc6f3906..f744464f31 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2631,7 +2631,7 @@ namespace OpenSim.Region.Framework.Scenes // Vector3 standPositionAdjustment // = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f); - Vector3 adjustmentForSitPosition = part.SitTargetPosition * part.GetWorldRotation(); + Vector3 adjustmentForSitPosition = (part.SitTargetPosition + OffsetPosition) * part.GetWorldRotation(); // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than // hardcoding here. From 0cc3cdfb4e7c0a74e60ceaad0528cabe857f65e8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 30 Aug 2014 00:48:59 +0100 Subject: [PATCH 12/15] As per the LL grid, for attachments make llGetObjectDetails() OBJECT_ROT return the avatar's rotation. This is already the behaviour of OBJECT_POS. Partially satisfies http://opensimulator.org/mantis/view.php?id=7177 --- .../Shared/Api/Implementation/LSL_Api.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5aef892eb9..7f91de206b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -11313,17 +11313,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); break; case ScriptBaseClass.OBJECT_ROT: - { - Quaternion rot = Quaternion.Identity; + Quaternion rot = Quaternion.Identity; + if (obj.ParentGroup.IsAttachment) + { + ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); + + if (sp != null) + rot = sp.GetWorldRotation(); + } + else + { if (obj.ParentGroup.RootPart == obj) rot = obj.ParentGroup.GroupRotation; else rot = obj.GetWorldRotation(); - - LSL_Rotation objrot = new LSL_Rotation(rot); - ret.Add(objrot); } + + LSL_Rotation objrot = new LSL_Rotation(rot); + ret.Add(objrot); + break; case ScriptBaseClass.OBJECT_VELOCITY: ret.Add(new LSL_Vector(obj.Velocity)); From 4d8bc007e2961df33d1fc36828b5f4d720beac22 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 30 Aug 2014 00:54:36 +0100 Subject: [PATCH 13/15] minor: fix wrong indentation in previous commit 0cc3cd --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7f91de206b..ab4115603a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -11317,7 +11317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.ParentGroup.IsAttachment) { - ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); + ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); if (sp != null) rot = sp.GetWorldRotation(); From bb7c88805a5b9eaad5be4183c9c9f71c102e1abf Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 30 Aug 2014 00:58:47 +0100 Subject: [PATCH 14/15] As per the LL grid, for attachments make llGetObjectDetails() OBJECT_VELOCITY return the avatar's velocity and not always Vector3.Zero. This completes http://opensimulator.org/mantis/view.php?id=7177 --- .../Shared/Api/Implementation/LSL_Api.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ab4115603a..5d7fc9db0d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -11335,7 +11335,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case ScriptBaseClass.OBJECT_VELOCITY: - ret.Add(new LSL_Vector(obj.Velocity)); + Vector3 vel = Vector3.Zero; + + if (obj.ParentGroup.IsAttachment) + { + ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); + + if (sp != null) + vel = sp.Velocity; + } + else + { + vel = obj.Velocity; + } + + ret.Add(vel); break; case ScriptBaseClass.OBJECT_OWNER: ret.Add(new LSL_String(obj.OwnerID.ToString())); From 473c559478ab56872f0e9d1bea3971b849df0b15 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 30 Aug 2014 01:09:33 +0100 Subject: [PATCH 15/15] As per the LL grid, if an avatar is sitting then return it's velocity relative to the region rather than relative to its seat. Resolves http://opensimulator.org/mantis/view.php?id=7175 --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f744464f31..e0b76407c7 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -622,9 +622,14 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", // m_velocity, Name, Scene.RegionInfo.RegionName); } + else if (ParentPart != null) + { + return ParentPart.ParentGroup.Velocity; + } return m_velocity; } + set { if (PhysicsActor != null)