diff options
author | Justin Clark-Casey (justincc) | 2012-10-24 02:05:28 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-10-24 02:05:28 +0100 |
commit | 73db057fa1dbda7d6dff7de770cef8670b234f84 (patch) | |
tree | 6f20e418aafe23b6a21044195dd100afa9aa65de | |
parent | Merge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff) | |
download | opensim-SC-73db057fa1dbda7d6dff7de770cef8670b234f84.zip opensim-SC-73db057fa1dbda7d6dff7de770cef8670b234f84.tar.gz opensim-SC-73db057fa1dbda7d6dff7de770cef8670b234f84.tar.bz2 opensim-SC-73db057fa1dbda7d6dff7de770cef8670b234f84.tar.xz |
Add "dump object uuid" console command. This allows any object in the scene to be serialized and dumped to XML for debug purposes.
-rw-r--r-- | OpenSim/Framework/Console/ConsoleUtil.cs | 206 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | 53 |
2 files changed, 168 insertions, 91 deletions
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs index 027753d..5c25ccb 100644 --- a/OpenSim/Framework/Console/ConsoleUtil.cs +++ b/OpenSim/Framework/Console/ConsoleUtil.cs | |||
@@ -32,100 +32,124 @@ using System.Reflection; | |||
32 | using log4net; | 32 | using log4net; |
33 | using OpenMetaverse; | 33 | using OpenMetaverse; |
34 | 34 | ||
35 | public class ConsoleUtil | 35 | namespace OpenSim.Framework.Console |
36 | { | 36 | { |
37 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 37 | public class ConsoleUtil |
38 | |||
39 | /// <summary> | ||
40 | /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section | ||
41 | /// rather than in each help summary. | ||
42 | /// </summary> | ||
43 | public const string CoordHelp | ||
44 | = @"Each component of the coord is comma separated. There must be no spaces between the commas. | ||
45 | If you don't care about the z component you can simply omit it. | ||
46 | If you don't care about the x or y components then you can leave them blank (though a comma is still required) | ||
47 | If you want to specify the maxmimum value of a component then you can use ~ instead of a number | ||
48 | If you want to specify the minimum value of a component then you can use -~ instead of a number | ||
49 | e.g. | ||
50 | delete object pos 20,20,20 to 40,40,40 | ||
51 | delete object pos 20,20 to 40,40 | ||
52 | delete object pos ,20,20 to ,40,40 | ||
53 | delete object pos ,,30 to ,,~ | ||
54 | delete object pos ,,-~ to ,,30"; | ||
55 | |||
56 | public const string MinRawConsoleVectorValue = "-~"; | ||
57 | public const string MaxRawConsoleVectorValue = "~"; | ||
58 | |||
59 | public const string VectorSeparator = ","; | ||
60 | public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); | ||
61 | |||
62 | /// <summary> | ||
63 | /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 | ||
64 | /// </summary> | ||
65 | /// <param name='rawConsoleVector'>/param> | ||
66 | /// <param name='vector'></param> | ||
67 | /// <returns></returns> | ||
68 | public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) | ||
69 | { | 38 | { |
70 | return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); | 39 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
71 | } | 40 | |
72 | 41 | /// <summary> | |
73 | /// <summary> | 42 | /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section |
74 | /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 | 43 | /// rather than in each help summary. |
75 | /// </summary> | 44 | /// </summary> |
76 | /// <param name='rawConsoleVector'>/param> | 45 | public const string CoordHelp |
77 | /// <param name='vector'></param> | 46 | = @"Each component of the coord is comma separated. There must be no spaces between the commas. |
78 | /// <returns></returns> | 47 | If you don't care about the z component you can simply omit it. |
79 | public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) | 48 | If you don't care about the x or y components then you can leave them blank (though a comma is still required) |
80 | { | 49 | If you want to specify the maxmimum value of a component then you can use ~ instead of a number |
81 | return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); | 50 | If you want to specify the minimum value of a component then you can use -~ instead of a number |
82 | } | 51 | e.g. |
83 | 52 | delete object pos 20,20,20 to 40,40,40 | |
84 | /// <summary> | 53 | delete object pos 20,20 to 40,40 |
85 | /// Convert a vector input from the console to an OpenMetaverse.Vector3 | 54 | delete object pos ,20,20 to ,40,40 |
86 | /// </summary> | 55 | delete object pos ,,30 to ,,~ |
87 | /// <param name='rawConsoleVector'> | 56 | delete object pos ,,-~ to ,,30"; |
88 | /// A string in the form <x>,<y>,<z> where there is no space between values. | 57 | |
89 | /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value | 58 | public const string MinRawConsoleVectorValue = "-~"; |
90 | /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) | 59 | public const string MaxRawConsoleVectorValue = "~"; |
91 | /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue | 60 | |
92 | /// Other than that, component values must be numeric. | 61 | public const string VectorSeparator = ","; |
93 | /// </param> | 62 | public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); |
94 | /// <param name='blankComponentFunc'></param> | 63 | |
95 | /// <param name='vector'></param> | 64 | /// <summary> |
96 | /// <returns></returns> | 65 | /// Try to parse a console UUID from the console. |
97 | public static bool TryParseConsoleVector( | 66 | /// </summary> |
98 | string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector) | 67 | /// <remarks> |
99 | { | 68 | /// Will complain to the console if parsing fails. |
100 | List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); | 69 | /// </remarks> |
101 | 70 | /// <returns></returns> | |
102 | if (components.Count < 1 || components.Count > 3) | 71 | /// <param name='console'></param> |
72 | /// <param name='rawUuid'></param> | ||
73 | /// <param name='uuid'></param> | ||
74 | public static bool TryParseConsoleUuid(ICommandConsole console, string rawUuid, out UUID uuid) | ||
103 | { | 75 | { |
104 | vector = Vector3.Zero; | 76 | if (!UUID.TryParse(rawUuid, out uuid)) |
105 | return false; | 77 | { |
78 | console.OutputFormat("{0} is not a valid uuid", rawUuid); | ||
79 | return false; | ||
80 | } | ||
81 | |||
82 | return true; | ||
83 | } | ||
84 | |||
85 | /// <summary> | ||
86 | /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 | ||
87 | /// </summary> | ||
88 | /// <param name='rawConsoleVector'>/param> | ||
89 | /// <param name='vector'></param> | ||
90 | /// <returns></returns> | ||
91 | public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) | ||
92 | { | ||
93 | return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); | ||
94 | } | ||
95 | |||
96 | /// <summary> | ||
97 | /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 | ||
98 | /// </summary> | ||
99 | /// <param name='rawConsoleVector'>/param> | ||
100 | /// <param name='vector'></param> | ||
101 | /// <returns></returns> | ||
102 | public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) | ||
103 | { | ||
104 | return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); | ||
105 | } | ||
106 | |||
107 | /// <summary> | ||
108 | /// Convert a vector input from the console to an OpenMetaverse.Vector3 | ||
109 | /// </summary> | ||
110 | /// <param name='rawConsoleVector'> | ||
111 | /// A string in the form <x>,<y>,<z> where there is no space between values. | ||
112 | /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value | ||
113 | /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) | ||
114 | /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue | ||
115 | /// Other than that, component values must be numeric. | ||
116 | /// </param> | ||
117 | /// <param name='blankComponentFunc'></param> | ||
118 | /// <param name='vector'></param> | ||
119 | /// <returns></returns> | ||
120 | public static bool TryParseConsoleVector( | ||
121 | string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector) | ||
122 | { | ||
123 | List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); | ||
124 | |||
125 | if (components.Count < 1 || components.Count > 3) | ||
126 | { | ||
127 | vector = Vector3.Zero; | ||
128 | return false; | ||
129 | } | ||
130 | |||
131 | for (int i = components.Count; i < 3; i++) | ||
132 | components.Add(""); | ||
133 | |||
134 | List<string> semiDigestedComponents | ||
135 | = components.ConvertAll<string>( | ||
136 | c => | ||
137 | { | ||
138 | if (c == "") | ||
139 | return blankComponentFunc.Invoke(c); | ||
140 | else if (c == MaxRawConsoleVectorValue) | ||
141 | return float.MaxValue.ToString(); | ||
142 | else if (c == MinRawConsoleVectorValue) | ||
143 | return float.MinValue.ToString(); | ||
144 | else | ||
145 | return c; | ||
146 | }); | ||
147 | |||
148 | string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); | ||
149 | |||
150 | // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); | ||
151 | |||
152 | return Vector3.TryParse(semiDigestedConsoleVector, out vector); | ||
106 | } | 153 | } |
107 | |||
108 | for (int i = components.Count; i < 3; i++) | ||
109 | components.Add(""); | ||
110 | |||
111 | List<string> semiDigestedComponents | ||
112 | = components.ConvertAll<string>( | ||
113 | c => | ||
114 | { | ||
115 | if (c == "") | ||
116 | return blankComponentFunc.Invoke(c); | ||
117 | else if (c == MaxRawConsoleVectorValue) | ||
118 | return float.MaxValue.ToString(); | ||
119 | else if (c == MinRawConsoleVectorValue) | ||
120 | return float.MinValue.ToString(); | ||
121 | else | ||
122 | return c; | ||
123 | }); | ||
124 | |||
125 | string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); | ||
126 | |||
127 | // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); | ||
128 | |||
129 | return Vector3.TryParse(semiDigestedConsoleVector, out vector); | ||
130 | } | 154 | } |
131 | } \ No newline at end of file | 155 | } \ 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 6435ae6..41a1afd 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | |||
@@ -27,10 +27,12 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | ||
30 | using System.Linq; | 31 | using System.Linq; |
31 | using System.Reflection; | 32 | using System.Reflection; |
32 | using System.Text; | 33 | using System.Text; |
33 | using System.Text.RegularExpressions; | 34 | using System.Text.RegularExpressions; |
35 | using System.Xml; | ||
34 | using log4net; | 36 | using log4net; |
35 | using Mono.Addins; | 37 | using Mono.Addins; |
36 | using NDesk.Options; | 38 | using NDesk.Options; |
@@ -41,6 +43,7 @@ using OpenSim.Framework.Console; | |||
41 | using OpenSim.Framework.Monitoring; | 43 | using OpenSim.Framework.Monitoring; |
42 | using OpenSim.Region.Framework.Interfaces; | 44 | using OpenSim.Region.Framework.Interfaces; |
43 | using OpenSim.Region.Framework.Scenes; | 45 | using OpenSim.Region.Framework.Scenes; |
46 | using OpenSim.Region.Framework.Scenes.Serialization; | ||
44 | 47 | ||
45 | namespace OpenSim.Region.CoreModules.World.Objects.Commands | 48 | namespace OpenSim.Region.CoreModules.World.Objects.Commands |
46 | { | 49 | { |
@@ -181,6 +184,16 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
181 | "Show details of scene object parts within the given area.", | 184 | "Show details of scene object parts within the given area.", |
182 | ConsoleUtil.CoordHelp, | 185 | ConsoleUtil.CoordHelp, |
183 | HandleShowPartByPos); | 186 | HandleShowPartByPos); |
187 | |||
188 | m_console.Commands.AddCommand( | ||
189 | "Objects", | ||
190 | false, | ||
191 | "dump object uuid", | ||
192 | "dump object uuid <UUID>", | ||
193 | "Dump the formatted serialization of the given object to the file <UUID>.xml", | ||
194 | "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" | ||
195 | + "To locate the UUID in the first place, you need to use the other show object commands", | ||
196 | HandleDumpObjectByUuid); | ||
184 | } | 197 | } |
185 | 198 | ||
186 | public void RemoveRegion(Scene scene) | 199 | public void RemoveRegion(Scene scene) |
@@ -447,6 +460,46 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands | |||
447 | OutputSopsToConsole(searchPredicate, true); | 460 | OutputSopsToConsole(searchPredicate, true); |
448 | } | 461 | } |
449 | 462 | ||
463 | private void HandleDumpObjectByUuid(string module, string[] cmdparams) | ||
464 | { | ||
465 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) | ||
466 | return; | ||
467 | |||
468 | if (cmdparams.Length < 4) | ||
469 | { | ||
470 | m_console.OutputFormat("Usage: dump object uuid <uuid>"); | ||
471 | return; | ||
472 | } | ||
473 | |||
474 | UUID objectUuid; | ||
475 | if (!ConsoleUtil.TryParseConsoleUuid(m_console, cmdparams[3], out objectUuid)) | ||
476 | return; | ||
477 | |||
478 | SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); | ||
479 | |||
480 | if (so == null) | ||
481 | { | ||
482 | // m_console.OutputFormat("No part found with uuid {0}", objectUuid); | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | string fileName = string.Format("{0}.xml", objectUuid); | ||
487 | |||
488 | if (File.Exists(fileName)) | ||
489 | { | ||
490 | m_console.OutputFormat("File {0} already exists. Please move or remove it.", fileName); | ||
491 | return; | ||
492 | } | ||
493 | |||
494 | using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) | ||
495 | { | ||
496 | xtw.Formatting = Formatting.Indented; | ||
497 | SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); | ||
498 | } | ||
499 | |||
500 | m_console.OutputFormat("Object dumped to file {0}", fileName); | ||
501 | } | ||
502 | |||
450 | /// <summary> | 503 | /// <summary> |
451 | /// Append a scene object report to an input StringBuilder | 504 | /// Append a scene object report to an input StringBuilder |
452 | /// </summary> | 505 | /// </summary> |