diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs index 027753d86c..5c25ccb76c 100644 --- a/OpenSim/Framework/Console/ConsoleUtil.cs +++ b/OpenSim/Framework/Console/ConsoleUtil.cs @@ -32,100 +32,124 @@ using System.Reflection; using log4net; using OpenMetaverse; -public class ConsoleUtil +namespace OpenSim.Framework.Console { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section - /// rather than in each help summary. - /// - public const string CoordHelp -= @"Each component of the coord is comma separated. There must be no spaces between the commas. -If you don't care about the z component you can simply omit it. -If you don't care about the x or y components then you can leave them blank (though a comma is still required) -If you want to specify the maxmimum value of a component then you can use ~ instead of a number -If you want to specify the minimum value of a component then you can use -~ instead of a number -e.g. -delete object pos 20,20,20 to 40,40,40 -delete object pos 20,20 to 40,40 -delete object pos ,20,20 to ,40,40 -delete object pos ,,30 to ,,~ -delete object pos ,,-~ to ,,30"; - - public const string MinRawConsoleVectorValue = "-~"; - public const string MaxRawConsoleVectorValue = "~"; - - public const string VectorSeparator = ","; - public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); - - /// - /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 - /// - /// /param> - /// - /// - public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) + public class ConsoleUtil { - return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); - } - - /// - /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 - /// - /// /param> - /// - /// - public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) - { - return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); - } - - /// - /// Convert a vector input from the console to an OpenMetaverse.Vector3 - /// - /// - /// A string in the form ,, where there is no space between values. - /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value - /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) - /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue - /// Other than that, component values must be numeric. - /// - /// - /// - /// - public static bool TryParseConsoleVector( - string rawConsoleVector, Func blankComponentFunc, out Vector3 vector) - { - List components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); - - if (components.Count < 1 || components.Count > 3) + // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section + /// rather than in each help summary. + /// + public const string CoordHelp + = @"Each component of the coord is comma separated. There must be no spaces between the commas. + If you don't care about the z component you can simply omit it. + If you don't care about the x or y components then you can leave them blank (though a comma is still required) + If you want to specify the maxmimum value of a component then you can use ~ instead of a number + If you want to specify the minimum value of a component then you can use -~ instead of a number + e.g. + delete object pos 20,20,20 to 40,40,40 + delete object pos 20,20 to 40,40 + delete object pos ,20,20 to ,40,40 + delete object pos ,,30 to ,,~ + delete object pos ,,-~ to ,,30"; + + public const string MinRawConsoleVectorValue = "-~"; + public const string MaxRawConsoleVectorValue = "~"; + + public const string VectorSeparator = ","; + public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); + + /// + /// Try to parse a console UUID from the console. + /// + /// + /// Will complain to the console if parsing fails. + /// + /// + /// + /// + /// + public static bool TryParseConsoleUuid(ICommandConsole console, string rawUuid, out UUID uuid) { - vector = Vector3.Zero; - return false; + if (!UUID.TryParse(rawUuid, out uuid)) + { + console.OutputFormat("{0} is not a valid uuid", rawUuid); + return false; + } + + return true; + } + + /// + /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 + /// + /// /param> + /// + /// + public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) + { + return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); + } + + /// + /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 + /// + /// /param> + /// + /// + public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) + { + return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); + } + + /// + /// Convert a vector input from the console to an OpenMetaverse.Vector3 + /// + /// + /// A string in the form ,, where there is no space between values. + /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value + /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) + /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue + /// Other than that, component values must be numeric. + /// + /// + /// + /// + public static bool TryParseConsoleVector( + string rawConsoleVector, Func blankComponentFunc, out Vector3 vector) + { + List components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); + + if (components.Count < 1 || components.Count > 3) + { + vector = Vector3.Zero; + return false; + } + + for (int i = components.Count; i < 3; i++) + components.Add(""); + + List semiDigestedComponents + = components.ConvertAll( + c => + { + if (c == "") + return blankComponentFunc.Invoke(c); + else if (c == MaxRawConsoleVectorValue) + return float.MaxValue.ToString(); + else if (c == MinRawConsoleVectorValue) + return float.MinValue.ToString(); + else + return c; + }); + + string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); + + // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); + + return Vector3.TryParse(semiDigestedConsoleVector, out vector); } - - for (int i = components.Count; i < 3; i++) - components.Add(""); - - List semiDigestedComponents - = components.ConvertAll( - c => - { - if (c == "") - return blankComponentFunc.Invoke(c); - else if (c == MaxRawConsoleVectorValue) - return float.MaxValue.ToString(); - else if (c == MinRawConsoleVectorValue) - return float.MinValue.ToString(); - else - return c; - }); - - string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); - -// m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); - - return Vector3.TryParse(semiDigestedConsoleVector, out vector); } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 6435ae6d1e..41a1afd643 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -27,10 +27,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using System.Xml; using log4net; using Mono.Addins; using NDesk.Options; @@ -41,6 +43,7 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; namespace OpenSim.Region.CoreModules.World.Objects.Commands { @@ -181,6 +184,16 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Show details of scene object parts within the given area.", ConsoleUtil.CoordHelp, HandleShowPartByPos); + + m_console.Commands.AddCommand( + "Objects", + false, + "dump object uuid", + "dump object uuid ", + "Dump the formatted serialization of the given object to the file .xml", + "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" + + "To locate the UUID in the first place, you need to use the other show object commands", + HandleDumpObjectByUuid); } public void RemoveRegion(Scene scene) @@ -447,6 +460,46 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSopsToConsole(searchPredicate, true); } + private void HandleDumpObjectByUuid(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmdparams.Length < 4) + { + m_console.OutputFormat("Usage: dump object uuid "); + return; + } + + UUID objectUuid; + if (!ConsoleUtil.TryParseConsoleUuid(m_console, cmdparams[3], out objectUuid)) + return; + + SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); + + if (so == null) + { +// m_console.OutputFormat("No part found with uuid {0}", objectUuid); + return; + } + + string fileName = string.Format("{0}.xml", objectUuid); + + if (File.Exists(fileName)) + { + m_console.OutputFormat("File {0} already exists. Please move or remove it.", fileName); + return; + } + + using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) + { + xtw.Formatting = Formatting.Indented; + SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); + } + + m_console.OutputFormat("Object dumped to file {0}", fileName); + } + /// /// Append a scene object report to an input StringBuilder ///