opensim-development – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | eva | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ |
||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * * Redistributions of source code must retain the above copyright |
||
8 | * notice, this list of conditions and the following disclaimer. |
||
9 | * * Redistributions in binary form must reproduce the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer in the |
||
11 | * documentation and/or other materials provided with the distribution. |
||
12 | * * Neither the name of the OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections.Generic; |
||
30 | using System.IO; |
||
31 | using System.Linq; |
||
32 | using System.Reflection; |
||
33 | using System.Text; |
||
34 | using System.Text.RegularExpressions; |
||
35 | using System.Xml; |
||
36 | using log4net; |
||
37 | using Mono.Addins; |
||
38 | using NDesk.Options; |
||
39 | using Nini.Config; |
||
40 | using OpenMetaverse; |
||
41 | using OpenSim.Framework; |
||
42 | using OpenSim.Framework.Console; |
||
43 | using OpenSim.Framework.Monitoring; |
||
44 | using OpenSim.Region.Framework.Interfaces; |
||
45 | using OpenSim.Region.Framework.Scenes; |
||
46 | using OpenSim.Region.Framework.Scenes.Serialization; |
||
47 | |||
48 | namespace OpenSim.Region.CoreModules.World.Objects.Commands |
||
49 | { |
||
50 | /// <summary> |
||
51 | /// A module that holds commands for manipulating objects in the scene. |
||
52 | /// </summary> |
||
53 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectCommandsModule")] |
||
54 | public class ObjectCommandsModule : INonSharedRegionModule |
||
55 | { |
||
56 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
57 | |||
58 | private Scene m_scene; |
||
59 | private ICommandConsole m_console; |
||
60 | |||
61 | public string Name { get { return "Object Commands Module"; } } |
||
62 | |||
63 | public Type ReplaceableInterface { get { return null; } } |
||
64 | |||
65 | public void Initialise(IConfigSource source) |
||
66 | { |
||
67 | // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE"); |
||
68 | } |
||
69 | |||
70 | public void PostInitialise() |
||
71 | { |
||
72 | // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE"); |
||
73 | } |
||
74 | |||
75 | public void Close() |
||
76 | { |
||
77 | // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE"); |
||
78 | } |
||
79 | |||
80 | public void AddRegion(Scene scene) |
||
81 | { |
||
82 | // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); |
||
83 | |||
84 | m_scene = scene; |
||
85 | m_console = MainConsole.Instance; |
||
86 | |||
87 | m_console.Commands.AddCommand( |
||
88 | "Objects", false, "delete object owner", |
||
89 | "delete object owner <UUID>", |
||
90 | "Delete scene objects by owner", |
||
91 | "Command will ask for confirmation before proceeding.", |
||
92 | HandleDeleteObject); |
||
93 | |||
94 | m_console.Commands.AddCommand( |
||
95 | "Objects", false, "delete object creator", |
||
96 | "delete object creator <UUID>", |
||
97 | "Delete scene objects by creator", |
||
98 | "Command will ask for confirmation before proceeding.", |
||
99 | HandleDeleteObject); |
||
100 | |||
101 | m_console.Commands.AddCommand( |
||
102 | "Objects", false, "delete object id", |
||
103 | "delete object id <UUID-or-localID>", |
||
104 | "Delete a scene object by uuid or localID", |
||
105 | HandleDeleteObject); |
||
106 | |||
107 | m_console.Commands.AddCommand( |
||
108 | "Objects", false, "delete object name", |
||
109 | "delete object name [--regex] <name>", |
||
110 | "Delete a scene object by name.", |
||
111 | "Command will ask for confirmation before proceeding.\n" |
||
112 | + "If --regex is specified then the name is treatead as a regular expression", |
||
113 | HandleDeleteObject); |
||
114 | |||
115 | m_console.Commands.AddCommand( |
||
116 | "Objects", false, "delete object outside", |
||
117 | "delete object outside", |
||
118 | "Delete all scene objects outside region boundaries", |
||
119 | "Command will ask for confirmation before proceeding.", |
||
120 | HandleDeleteObject); |
||
121 | |||
122 | m_console.Commands.AddCommand( |
||
123 | "Objects", |
||
124 | false, |
||
125 | "delete object pos", |
||
126 | "delete object pos <start-coord> to <end-coord>", |
||
127 | "Delete scene objects within the given area.", |
||
128 | ConsoleUtil.CoordHelp, |
||
129 | HandleDeleteObject); |
||
130 | |||
131 | m_console.Commands.AddCommand( |
||
132 | "Objects", |
||
133 | false, |
||
134 | "show object id", |
||
135 | "show object id [--full] <UUID-or-localID>", |
||
136 | "Show details of a scene object with the given UUID or localID", |
||
137 | "The --full option will print out information on all the parts of the object.\n" |
||
138 | + "For yet more detailed part information, use the \"show part\" commands.", |
||
139 | HandleShowObjectById); |
||
140 | |||
141 | m_console.Commands.AddCommand( |
||
142 | "Objects", |
||
143 | false, |
||
144 | "show object name", |
||
145 | "show object name [--full] [--regex] <name>", |
||
146 | "Show details of scene objects with the given name.", |
||
147 | "The --full option will print out information on all the parts of the object.\n" |
||
148 | + "For yet more detailed part information, use the \"show part\" commands.\n" |
||
149 | + "If --regex is specified then the name is treatead as a regular expression.", |
||
150 | HandleShowObjectByName); |
||
151 | |||
152 | m_console.Commands.AddCommand( |
||
153 | "Objects", |
||
154 | false, |
||
155 | "show object pos", |
||
156 | "show object pos [--full] <start-coord> to <end-coord>", |
||
157 | "Show details of scene objects within the given area.", |
||
158 | "The --full option will print out information on all the parts of the object.\n" |
||
159 | + "For yet more detailed part information, use the \"show part\" commands.\n" |
||
160 | + ConsoleUtil.CoordHelp, |
||
161 | HandleShowObjectByPos); |
||
162 | |||
163 | m_console.Commands.AddCommand( |
||
164 | "Objects", |
||
165 | false, |
||
166 | "show part id", |
||
167 | "show part id <UUID-or-localID>", |
||
168 | "Show details of a scene object part with the given UUID or localID", HandleShowPartById); |
||
169 | |||
170 | m_console.Commands.AddCommand( |
||
171 | "Objects", |
||
172 | false, |
||
173 | "show part name", |
||
174 | "show part name [--regex] <name>", |
||
175 | "Show details of scene object parts with the given name.", |
||
176 | "If --regex is specified then the name is treated as a regular expression", |
||
177 | HandleShowPartByName); |
||
178 | |||
179 | m_console.Commands.AddCommand( |
||
180 | "Objects", |
||
181 | false, |
||
182 | "show part pos", |
||
183 | "show part pos <start-coord> to <end-coord>", |
||
184 | "Show details of scene object parts within the given area.", |
||
185 | ConsoleUtil.CoordHelp, |
||
186 | HandleShowPartByPos); |
||
187 | |||
188 | m_console.Commands.AddCommand( |
||
189 | "Objects", |
||
190 | false, |
||
191 | "dump object id", |
||
192 | "dump object id <UUID-or-localID>", |
||
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 or localID in the first place, you need to use the other show object commands.\n" |
||
196 | + "If a local ID is given then the filename used is still that for the UUID", |
||
197 | HandleDumpObjectById); |
||
198 | } |
||
199 | |||
200 | public void RemoveRegion(Scene scene) |
||
201 | { |
||
202 | // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); |
||
203 | } |
||
204 | |||
205 | public void RegionLoaded(Scene scene) |
||
206 | { |
||
207 | // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); |
||
208 | } |
||
209 | |||
210 | /// <summary> |
||
211 | /// Outputs the sogs to console. |
||
212 | /// </summary> |
||
213 | /// <param name='searchPredicate'></param> |
||
214 | /// <param name='showFull'>If true then output all part details. If false then output summary.</param> |
||
215 | private void OutputSogsToConsole(Predicate<SceneObjectGroup> searchPredicate, bool showFull) |
||
216 | { |
||
217 | List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); |
||
218 | |||
219 | StringBuilder sb = new StringBuilder(); |
||
220 | |||
221 | foreach (SceneObjectGroup so in sceneObjects) |
||
222 | { |
||
223 | AddSceneObjectReport(sb, so, showFull); |
||
224 | sb.Append("\n"); |
||
225 | } |
||
226 | |||
227 | sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name); |
||
228 | |||
229 | m_console.OutputFormat(sb.ToString()); |
||
230 | } |
||
231 | |||
232 | private void OutputSopsToConsole(Predicate<SceneObjectPart> searchPredicate, bool showFull) |
||
233 | { |
||
234 | List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups(); |
||
235 | List<SceneObjectPart> parts = new List<SceneObjectPart>(); |
||
236 | |||
237 | sceneObjects.ForEach(so => parts.AddRange(Array.FindAll<SceneObjectPart>(so.Parts, searchPredicate))); |
||
238 | |||
239 | StringBuilder sb = new StringBuilder(); |
||
240 | |||
241 | foreach (SceneObjectPart part in parts) |
||
242 | { |
||
243 | AddScenePartReport(sb, part, showFull); |
||
244 | sb.Append("\n"); |
||
245 | } |
||
246 | |||
247 | sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); |
||
248 | |||
249 | m_console.OutputFormat(sb.ToString()); |
||
250 | } |
||
251 | |||
252 | private void HandleShowObjectById(string module, string[] cmdparams) |
||
253 | { |
||
254 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
255 | return; |
||
256 | |||
257 | bool showFull = false; |
||
258 | OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); |
||
259 | |||
260 | List<string> mainParams = options.Parse(cmdparams); |
||
261 | |||
262 | if (mainParams.Count < 4) |
||
263 | { |
||
264 | m_console.OutputFormat("Usage: show object uuid <uuid>"); |
||
265 | return; |
||
266 | } |
||
267 | |||
268 | UUID uuid; |
||
269 | uint localId; |
||
270 | if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) |
||
271 | return; |
||
272 | |||
273 | SceneObjectGroup so; |
||
274 | |||
275 | if (localId != ConsoleUtil.LocalIdNotFound) |
||
276 | so = m_scene.GetSceneObjectGroup(localId); |
||
277 | else |
||
278 | so = m_scene.GetSceneObjectGroup(uuid); |
||
279 | |||
280 | if (so == null) |
||
281 | { |
||
282 | // m_console.OutputFormat("No part found with uuid {0}", objectUuid); |
||
283 | return; |
||
284 | } |
||
285 | |||
286 | StringBuilder sb = new StringBuilder(); |
||
287 | AddSceneObjectReport(sb, so, showFull); |
||
288 | |||
289 | m_console.OutputFormat(sb.ToString()); |
||
290 | } |
||
291 | |||
292 | private void HandleShowObjectByName(string module, string[] cmdparams) |
||
293 | { |
||
294 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
295 | return; |
||
296 | |||
297 | bool showFull = false; |
||
298 | bool useRegex = false; |
||
299 | OptionSet options = new OptionSet(); |
||
300 | options.Add("full", v => showFull = v != null ); |
||
301 | options.Add("regex", v => useRegex = v != null ); |
||
302 | |||
303 | List<string> mainParams = options.Parse(cmdparams); |
||
304 | |||
305 | if (mainParams.Count < 4) |
||
306 | { |
||
307 | m_console.OutputFormat("Usage: show object name [--full] [--regex] <name>"); |
||
308 | return; |
||
309 | } |
||
310 | |||
311 | string name = mainParams[3]; |
||
312 | |||
313 | Predicate<SceneObjectGroup> searchPredicate; |
||
314 | |||
315 | if (useRegex) |
||
316 | { |
||
317 | Regex nameRegex = new Regex(name); |
||
318 | searchPredicate = so => nameRegex.IsMatch(so.Name); |
||
319 | } |
||
320 | else |
||
321 | { |
||
322 | searchPredicate = so => so.Name == name; |
||
323 | } |
||
324 | |||
325 | OutputSogsToConsole(searchPredicate, showFull); |
||
326 | } |
||
327 | |||
328 | private void HandleShowObjectByPos(string module, string[] cmdparams) |
||
329 | { |
||
330 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
331 | return; |
||
332 | |||
333 | bool showFull = false; |
||
334 | OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); |
||
335 | |||
336 | List<string> mainParams = options.Parse(cmdparams); |
||
337 | |||
338 | if (mainParams.Count < 5) |
||
339 | { |
||
340 | m_console.OutputFormat("Usage: show object pos [--full] <start-coord> to <end-coord>"); |
||
341 | return; |
||
342 | } |
||
343 | |||
344 | Vector3 startVector, endVector; |
||
345 | |||
346 | if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) |
||
347 | return; |
||
348 | |||
349 | Predicate<SceneObjectGroup> searchPredicate |
||
350 | = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); |
||
351 | |||
352 | OutputSogsToConsole(searchPredicate, showFull); |
||
353 | } |
||
354 | |||
355 | private void HandleShowPartById(string module, string[] cmdparams) |
||
356 | { |
||
357 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
358 | return; |
||
359 | |||
360 | // bool showFull = false; |
||
361 | OptionSet options = new OptionSet(); |
||
362 | // options.Add("full", v => showFull = v != null ); |
||
363 | |||
364 | List<string> mainParams = options.Parse(cmdparams); |
||
365 | |||
366 | if (mainParams.Count < 4) |
||
367 | { |
||
368 | //m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>"); |
||
369 | m_console.OutputFormat("Usage: show part id <UUID-or-localID>"); |
||
370 | return; |
||
371 | } |
||
372 | |||
373 | UUID objectUuid; |
||
374 | uint localId; |
||
375 | if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) |
||
376 | return; |
||
377 | |||
378 | SceneObjectPart sop; |
||
379 | if (localId == ConsoleUtil.LocalIdNotFound) |
||
380 | sop = m_scene.GetSceneObjectPart(objectUuid); |
||
381 | else |
||
382 | sop = m_scene.GetSceneObjectPart(localId); |
||
383 | |||
384 | if (sop == null) |
||
385 | { |
||
386 | // m_console.OutputFormat("No part found with uuid {0}", objectUuid); |
||
387 | return; |
||
388 | } |
||
389 | |||
390 | StringBuilder sb = new StringBuilder(); |
||
391 | AddScenePartReport(sb, sop, true); |
||
392 | |||
393 | m_console.OutputFormat(sb.ToString()); |
||
394 | } |
||
395 | |||
396 | private void HandleShowPartByPos(string module, string[] cmdparams) |
||
397 | { |
||
398 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
399 | return; |
||
400 | |||
401 | // bool showFull = false; |
||
402 | OptionSet options = new OptionSet(); |
||
403 | // options.Add("full", v => showFull = v != null ); |
||
404 | |||
405 | List<string> mainParams = options.Parse(cmdparams); |
||
406 | |||
407 | if (mainParams.Count < 5) |
||
408 | { |
||
409 | //m_console.OutputFormat("Usage: show part pos <start-coord> to <end-coord>"); |
||
410 | m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>"); |
||
411 | return; |
||
412 | } |
||
413 | |||
414 | string rawConsoleStartVector = mainParams[3]; |
||
415 | Vector3 startVector; |
||
416 | |||
417 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) |
||
418 | { |
||
419 | m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector); |
||
420 | return; |
||
421 | } |
||
422 | |||
423 | string rawConsoleEndVector = mainParams[5]; |
||
424 | Vector3 endVector; |
||
425 | |||
426 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) |
||
427 | { |
||
428 | m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector); |
||
429 | return; |
||
430 | } |
||
431 | |||
432 | OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true); |
||
433 | } |
||
434 | |||
435 | private void HandleShowPartByName(string module, string[] cmdparams) |
||
436 | { |
||
437 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
438 | return; |
||
439 | |||
440 | // bool showFull = false; |
||
441 | bool useRegex = false; |
||
442 | OptionSet options = new OptionSet(); |
||
443 | // options.Add("full", v => showFull = v != null ); |
||
444 | options.Add("regex", v => useRegex = v != null ); |
||
445 | |||
446 | List<string> mainParams = options.Parse(cmdparams); |
||
447 | |||
448 | if (mainParams.Count < 4) |
||
449 | { |
||
450 | m_console.OutputFormat("Usage: show part name [--regex] <name>"); |
||
451 | //m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>"); |
||
452 | return; |
||
453 | } |
||
454 | |||
455 | string name = mainParams[3]; |
||
456 | |||
457 | Predicate<SceneObjectPart> searchPredicate; |
||
458 | |||
459 | if (useRegex) |
||
460 | { |
||
461 | Regex nameRegex = new Regex(name); |
||
462 | searchPredicate = sop => nameRegex.IsMatch(sop.Name); |
||
463 | } |
||
464 | else |
||
465 | { |
||
466 | searchPredicate = sop => sop.Name == name; |
||
467 | } |
||
468 | |||
469 | OutputSopsToConsole(searchPredicate, true); |
||
470 | } |
||
471 | |||
472 | private void HandleDumpObjectById(string module, string[] cmdparams) |
||
473 | { |
||
474 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
475 | return; |
||
476 | |||
477 | if (cmdparams.Length < 4) |
||
478 | { |
||
479 | m_console.OutputFormat("Usage: dump object id <UUID-or-localID>"); |
||
480 | return; |
||
481 | } |
||
482 | |||
483 | UUID objectUuid; |
||
484 | uint localId; |
||
485 | if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId)) |
||
486 | return; |
||
487 | |||
488 | SceneObjectGroup so; |
||
489 | if (localId == ConsoleUtil.LocalIdNotFound) |
||
490 | so = m_scene.GetSceneObjectGroup(objectUuid); |
||
491 | else |
||
492 | so = m_scene.GetSceneObjectGroup(localId); |
||
493 | |||
494 | if (so == null) |
||
495 | { |
||
496 | // m_console.OutputFormat("No part found with uuid {0}", objectUuid); |
||
497 | return; |
||
498 | } |
||
499 | |||
500 | // In case we found it via local ID. |
||
501 | objectUuid = so.UUID; |
||
502 | |||
503 | string fileName = string.Format("{0}.xml", objectUuid); |
||
504 | |||
505 | if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) |
||
506 | return; |
||
507 | |||
508 | using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) |
||
509 | { |
||
510 | xtw.Formatting = Formatting.Indented; |
||
511 | SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); |
||
512 | } |
||
513 | |||
514 | m_console.OutputFormat("Object dumped to file {0}", fileName); |
||
515 | } |
||
516 | |||
517 | /// <summary> |
||
518 | /// Append a scene object report to an input StringBuilder |
||
519 | /// </summary> |
||
520 | /// <returns></returns> |
||
521 | /// <param name='sb'></param> |
||
522 | /// <param name='so'</param> |
||
523 | /// <param name='showFull'> |
||
524 | /// If true then information on all parts of an object is appended. |
||
525 | /// If false then only summary information about an object is appended. |
||
526 | /// </param> |
||
527 | private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) |
||
528 | { |
||
529 | if (showFull) |
||
530 | { |
||
531 | foreach (SceneObjectPart sop in so.Parts) |
||
532 | { |
||
533 | AddScenePartReport(sb, sop, false); |
||
534 | sb.Append("\n"); |
||
535 | } |
||
536 | } |
||
537 | else |
||
538 | { |
||
539 | AddSummarySceneObjectReport(sb, so); |
||
540 | } |
||
541 | |||
542 | return sb; |
||
543 | } |
||
544 | |||
545 | private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) |
||
546 | { |
||
547 | ConsoleDisplayList cdl = new ConsoleDisplayList(); |
||
548 | cdl.AddRow("Name", so.Name); |
||
549 | cdl.AddRow("Description", so.Description); |
||
550 | cdl.AddRow("Local ID", so.LocalId); |
||
551 | cdl.AddRow("UUID", so.UUID); |
||
552 | cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); |
||
553 | cdl.AddRow("Parts", so.PrimCount); |
||
554 | cdl.AddRow("Flags", so.RootPart.Flags); |
||
555 | |||
556 | return sb.Append(cdl.ToString()); |
||
557 | } |
||
558 | |||
559 | /// <summary> |
||
560 | /// Append a scene object part report to an input StringBuilder |
||
561 | /// </summary> |
||
562 | /// <returns></returns> |
||
563 | /// <param name='sb'></param> |
||
564 | /// <param name='sop'</param> |
||
565 | /// <param name='showFull'> |
||
566 | /// If true then information on each inventory item will be shown. |
||
567 | /// If false then only summary inventory information is shown. |
||
568 | /// </param> |
||
569 | private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull) |
||
570 | { |
||
571 | ConsoleDisplayList cdl = new ConsoleDisplayList(); |
||
572 | cdl.AddRow("Name", sop.Name); |
||
573 | cdl.AddRow("Description", sop.Description); |
||
574 | cdl.AddRow("Local ID", sop.LocalId); |
||
575 | cdl.AddRow("UUID", sop.UUID); |
||
576 | cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name)); |
||
577 | cdl.AddRow( |
||
578 | "Parent", |
||
579 | sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); |
||
580 | cdl.AddRow("Link number", sop.LinkNum); |
||
581 | cdl.AddRow("Flags", sop.Flags); |
||
582 | |||
583 | if (showFull) |
||
584 | { |
||
585 | PrimitiveBaseShape s = sop.Shape; |
||
586 | cdl.AddRow("FlexiDrag", s.FlexiDrag); |
||
587 | cdl.AddRow("FlexiEntry", s.FlexiEntry); |
||
588 | cdl.AddRow("FlexiForce", string.Format("<{0},{1},{2}>", s.FlexiForceX, s.FlexiForceY, s.FlexiForceZ)); |
||
589 | cdl.AddRow("FlexiGravity", s.FlexiGravity); |
||
590 | cdl.AddRow("FlexiSoftness", s.FlexiSoftness); |
||
591 | cdl.AddRow("HollowShape", s.HollowShape); |
||
592 | cdl.AddRow( |
||
593 | "LightColor", |
||
594 | string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA)); |
||
595 | cdl.AddRow("LightCutoff", s.LightCutoff); |
||
596 | cdl.AddRow("LightEntry", s.LightEntry); |
||
597 | cdl.AddRow("LightFalloff", s.LightFalloff); |
||
598 | cdl.AddRow("LightIntensity", s.LightIntensity); |
||
599 | cdl.AddRow("LightRadius", s.LightRadius); |
||
600 | cdl.AddRow("Location (relative)", sop.RelativePosition); |
||
601 | cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a")); |
||
602 | cdl.AddRow("PathBegin", s.PathBegin); |
||
603 | cdl.AddRow("PathEnd", s.PathEnd); |
||
604 | cdl.AddRow("PathCurve", s.PathCurve); |
||
605 | cdl.AddRow("PathRadiusOffset", s.PathRadiusOffset); |
||
606 | cdl.AddRow("PathRevolutions", s.PathRevolutions); |
||
607 | cdl.AddRow("PathScale", string.Format("<{0},{1}>", s.PathScaleX, s.PathScaleY)); |
||
608 | cdl.AddRow("PathSkew", string.Format("<{0},{1}>", s.PathShearX, s.PathShearY)); |
||
609 | cdl.AddRow("FlexiDrag", s.PathSkew); |
||
610 | cdl.AddRow("PathTaper", string.Format("<{0},{1}>", s.PathTaperX, s.PathTaperY)); |
||
611 | cdl.AddRow("PathTwist", s.PathTwist); |
||
612 | cdl.AddRow("PathTwistBegin", s.PathTwistBegin); |
||
613 | cdl.AddRow("PCode", s.PCode); |
||
614 | cdl.AddRow("ProfileBegin", s.ProfileBegin); |
||
615 | cdl.AddRow("ProfileEnd", s.ProfileEnd); |
||
616 | cdl.AddRow("ProfileHollow", s.ProfileHollow); |
||
617 | cdl.AddRow("ProfileShape", s.ProfileShape); |
||
618 | cdl.AddRow("ProjectionAmbiance", s.ProjectionAmbiance); |
||
619 | cdl.AddRow("ProjectionEntry", s.ProjectionEntry); |
||
620 | cdl.AddRow("ProjectionFocus", s.ProjectionFocus); |
||
621 | cdl.AddRow("ProjectionFOV", s.ProjectionFOV); |
||
622 | cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID); |
||
623 | cdl.AddRow("Rotation (Relative)", sop.RotationOffset); |
||
624 | cdl.AddRow("Rotation (World)", sop.GetWorldRotation()); |
||
625 | cdl.AddRow("Scale", s.Scale); |
||
626 | cdl.AddRow( |
||
627 | "SculptData", |
||
628 | string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a")); |
||
629 | cdl.AddRow("SculptEntry", s.SculptEntry); |
||
630 | cdl.AddRow("SculptTexture", s.SculptTexture); |
||
631 | cdl.AddRow("SculptType", s.SculptType); |
||
632 | cdl.AddRow("State", s.State); |
||
633 | |||
634 | // TODO, need to display more information about textures but in a compact format |
||
635 | // to stop output becoming huge. |
||
636 | for (int i = 0; i < sop.GetNumberOfSides(); i++) |
||
637 | { |
||
638 | Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i]; |
||
639 | |||
640 | UUID textureID; |
||
641 | |||
642 | if (teFace != null) |
||
643 | textureID = teFace.TextureID; |
||
644 | else |
||
645 | textureID = s.Textures.DefaultTexture.TextureID; |
||
646 | |||
647 | cdl.AddRow(string.Format("Face {0} texture ID", i), textureID); |
||
648 | } |
||
649 | |||
650 | //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures. |
||
651 | } |
||
652 | |||
653 | object itemsOutput; |
||
654 | if (showFull) |
||
655 | { |
||
656 | StringBuilder itemsSb = new StringBuilder("\n"); |
||
657 | itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString(); |
||
658 | } |
||
659 | else |
||
660 | { |
||
661 | itemsOutput = sop.Inventory.Count; |
||
662 | } |
||
663 | |||
664 | cdl.AddRow("Items", itemsOutput); |
||
665 | |||
666 | return sb.Append(cdl.ToString()); |
||
667 | } |
||
668 | |||
669 | private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv) |
||
670 | { |
||
671 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
672 | cdt.Indent = 2; |
||
673 | |||
674 | cdt.AddColumn("Name", 50); |
||
675 | cdt.AddColumn("Type", 12); |
||
676 | cdt.AddColumn("Running", 7); |
||
677 | cdt.AddColumn("Item UUID", 36); |
||
678 | cdt.AddColumn("Asset UUID", 36); |
||
679 | |||
680 | foreach (TaskInventoryItem item in inv.GetInventoryItems()) |
||
681 | { |
||
682 | bool foundScriptInstance, scriptRunning; |
||
683 | foundScriptInstance |
||
684 | = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning); |
||
685 | |||
686 | cdt.AddRow( |
||
687 | item.Name, |
||
688 | ((InventoryType)item.InvType).ToString(), |
||
689 | foundScriptInstance ? scriptRunning.ToString() : "n/a", |
||
690 | item.ItemID.ToString(), |
||
691 | item.AssetID.ToString()); |
||
692 | } |
||
693 | |||
694 | return sb.Append(cdt.ToString()); |
||
695 | } |
||
696 | |||
697 | private void HandleDeleteObject(string module, string[] cmd) |
||
698 | { |
||
699 | if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) |
||
700 | return; |
||
701 | |||
702 | if (cmd.Length < 3) |
||
703 | return; |
||
704 | |||
705 | string mode = cmd[2]; |
||
706 | string o = ""; |
||
707 | |||
708 | if (mode != "outside") |
||
709 | { |
||
710 | if (cmd.Length < 4) |
||
711 | return; |
||
712 | |||
713 | o = cmd[3]; |
||
714 | } |
||
715 | |||
716 | List<SceneObjectGroup> deletes = null; |
||
717 | UUID match; |
||
718 | bool requireConfirmation = true; |
||
719 | |||
720 | switch (mode) |
||
721 | { |
||
722 | case "owner": |
||
723 | if (!UUID.TryParse(o, out match)) |
||
724 | return; |
||
725 | |||
726 | deletes = new List<SceneObjectGroup>(); |
||
727 | |||
728 | m_scene.ForEachSOG(delegate (SceneObjectGroup g) |
||
729 | { |
||
730 | if (g.OwnerID == match && !g.IsAttachment) |
||
731 | deletes.Add(g); |
||
732 | }); |
||
733 | |||
734 | // if (deletes.Count == 0) |
||
735 | // m_console.OutputFormat("No objects were found with owner {0}", match); |
||
736 | |||
737 | break; |
||
738 | |||
739 | case "creator": |
||
740 | if (!UUID.TryParse(o, out match)) |
||
741 | return; |
||
742 | |||
743 | deletes = new List<SceneObjectGroup>(); |
||
744 | |||
745 | m_scene.ForEachSOG(delegate (SceneObjectGroup g) |
||
746 | { |
||
747 | if (g.RootPart.CreatorID == match && !g.IsAttachment) |
||
748 | deletes.Add(g); |
||
749 | }); |
||
750 | |||
751 | // if (deletes.Count == 0) |
||
752 | // m_console.OutputFormat("No objects were found with creator {0}", match); |
||
753 | |||
754 | break; |
||
755 | |||
756 | case "id": |
||
757 | UUID uuid; |
||
758 | uint localId; |
||
759 | if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId)) |
||
760 | return; |
||
761 | |||
762 | requireConfirmation = false; |
||
763 | deletes = new List<SceneObjectGroup>(); |
||
764 | |||
765 | SceneObjectGroup so; |
||
766 | if (localId == ConsoleUtil.LocalIdNotFound) |
||
767 | so = m_scene.GetSceneObjectGroup(uuid); |
||
768 | else |
||
769 | so = m_scene.GetSceneObjectGroup(localId); |
||
770 | |||
771 | if (!so.IsAttachment) |
||
772 | deletes.Add(so); |
||
773 | |||
774 | // if (deletes.Count == 0) |
||
775 | // m_console.OutputFormat("No objects were found with uuid {0}", match); |
||
776 | |||
777 | break; |
||
778 | |||
779 | case "name": |
||
780 | deletes = GetDeleteCandidatesByName(module, cmd); |
||
781 | break; |
||
782 | |||
783 | case "outside": |
||
784 | deletes = new List<SceneObjectGroup>(); |
||
785 | |||
786 | m_scene.ForEachSOG(delegate (SceneObjectGroup g) |
||
787 | { |
||
788 | SceneObjectPart rootPart = g.RootPart; |
||
789 | bool delete = false; |
||
790 | |||
791 | if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) |
||
792 | { |
||
793 | delete = true; |
||
794 | } |
||
795 | else |
||
796 | { |
||
797 | ILandObject parcel |
||
798 | = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y); |
||
799 | |||
800 | if (parcel == null || parcel.LandData.Name == "NO LAND") |
||
801 | delete = true; |
||
802 | } |
||
803 | |||
804 | if (delete && !g.IsAttachment && !deletes.Contains(g)) |
||
805 | deletes.Add(g); |
||
806 | }); |
||
807 | |||
808 | if (deletes.Count == 0) |
||
809 | m_console.OutputFormat("No objects were found outside region bounds"); |
||
810 | |||
811 | break; |
||
812 | |||
813 | case "pos": |
||
814 | deletes = GetDeleteCandidatesByPos(module, cmd); |
||
815 | break; |
||
816 | |||
817 | default: |
||
818 | m_console.OutputFormat("Unrecognized mode {0}", mode); |
||
819 | return; |
||
820 | } |
||
821 | |||
822 | if (deletes == null || deletes.Count <= 0) |
||
823 | return; |
||
824 | |||
825 | if (requireConfirmation) |
||
826 | { |
||
827 | string response = MainConsole.Instance.CmdPrompt( |
||
828 | string.Format( |
||
829 | "Are you sure that you want to delete {0} objects from {1}", |
||
830 | deletes.Count, m_scene.RegionInfo.RegionName), |
||
831 | "y/N"); |
||
832 | |||
833 | if (response.ToLower() != "y") |
||
834 | { |
||
835 | MainConsole.Instance.OutputFormat( |
||
836 | "Aborting delete of {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName); |
||
837 | |||
838 | return; |
||
839 | } |
||
840 | } |
||
841 | |||
842 | m_console.OutputFormat("Deleting {0} objects in {1}", deletes.Count, m_scene.RegionInfo.RegionName); |
||
843 | |||
844 | foreach (SceneObjectGroup g in deletes) |
||
845 | { |
||
846 | m_console.OutputFormat("Deleting object {0} {1}", g.UUID, g.Name); |
||
847 | m_scene.DeleteSceneObject(g, false); |
||
848 | } |
||
849 | } |
||
850 | |||
851 | private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) |
||
852 | { |
||
853 | bool useRegex = false; |
||
854 | OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); |
||
855 | |||
856 | List<string> mainParams = options.Parse(cmdparams); |
||
857 | |||
858 | if (mainParams.Count < 4) |
||
859 | { |
||
860 | m_console.OutputFormat("Usage: delete object name [--regex] <name>"); |
||
861 | return null; |
||
862 | } |
||
863 | |||
864 | string name = mainParams[3]; |
||
865 | |||
866 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); |
||
867 | Action<SceneObjectGroup> searchAction; |
||
868 | |||
869 | if (useRegex) |
||
870 | { |
||
871 | Regex nameRegex = new Regex(name); |
||
872 | searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; |
||
873 | } |
||
874 | else |
||
875 | { |
||
876 | searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; |
||
877 | } |
||
878 | |||
879 | m_scene.ForEachSOG(searchAction); |
||
880 | |||
881 | if (sceneObjects.Count == 0) |
||
882 | m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); |
||
883 | |||
884 | return sceneObjects; |
||
885 | } |
||
886 | |||
887 | /// <summary> |
||
888 | /// Get scene object delete candidates by position |
||
889 | /// </summary> |
||
890 | /// <param name='module'></param> |
||
891 | /// <param name='cmdparams'></param> |
||
892 | /// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there |
||
893 | /// are no objects to delete then the list will be empty./returns> |
||
894 | private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams) |
||
895 | { |
||
896 | if (cmdparams.Length < 5) |
||
897 | { |
||
898 | m_console.OutputFormat("Usage: delete object pos <start-coord> to <end-coord>"); |
||
899 | return null; |
||
900 | } |
||
901 | |||
902 | Vector3 startVector, endVector; |
||
903 | |||
904 | if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) |
||
905 | return null; |
||
906 | |||
907 | return m_scene.GetSceneObjectGroups().FindAll( |
||
908 | so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)); |
||
909 | } |
||
910 | |||
911 | private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector) |
||
912 | { |
||
913 | string rawConsoleStartVector = rawComponents.Take(1).Single(); |
||
914 | |||
915 | if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) |
||
916 | { |
||
917 | m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector); |
||
918 | endVector = Vector3.Zero; |
||
919 | |||
920 | return false; |
||
921 | } |
||
922 | |||
923 | string rawConsoleEndVector = rawComponents.Skip(2).Take(1).Single(); |
||
924 | |||
925 | if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) |
||
926 | { |
||
927 | m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector); |
||
928 | return false; |
||
929 | } |
||
930 | |||
931 | return true; |
||
932 | } |
||
933 | } |
||
934 | } |