ObjectCommandsModule.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  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. using System;
  28. using System.Collections.Generic;
  29. using System.IO;
  30. using System.Linq;
  31. using System.Reflection;
  32. using System.Text;
  33. using System.Text.RegularExpressions;
  34. using System.Xml;
  35. using log4net;
  36. using Mono.Addins;
  37. using NDesk.Options;
  38. using Nini.Config;
  39. using OpenMetaverse;
  40. using OpenSim.Framework;
  41. using OpenSim.Framework.Console;
  42. using OpenSim.Framework.Monitoring;
  43. using OpenSim.Region.Framework.Interfaces;
  44. using OpenSim.Region.Framework.Scenes;
  45. using OpenSim.Region.Framework.Scenes.Serialization;
  46. namespace OpenSim.Region.CoreModules.World.Objects.Commands
  47. {
  48. /// <summary>
  49. /// A module that holds commands for manipulating objects in the scene.
  50. /// </summary>
  51. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectCommandsModule")]
  52. public class ObjectCommandsModule : INonSharedRegionModule
  53. {
  54. // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  55. private Scene m_scene;
  56. private ICommandConsole m_console;
  57. public string Name { get { return "Object Commands Module"; } }
  58. public Type ReplaceableInterface { get { return null; } }
  59. public void Initialise(IConfigSource source)
  60. {
  61. // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE");
  62. }
  63. public void PostInitialise()
  64. {
  65. // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE");
  66. }
  67. public void Close()
  68. {
  69. // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE");
  70. }
  71. public void AddRegion(Scene scene)
  72. {
  73. // m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
  74. m_scene = scene;
  75. m_console = MainConsole.Instance;
  76. m_console.Commands.AddCommand(
  77. "Objects", false, "delete object owner",
  78. "delete object owner <UUID>",
  79. "Delete scene objects by owner",
  80. "Command will ask for confirmation before proceeding.",
  81. HandleDeleteObject);
  82. m_console.Commands.AddCommand(
  83. "Objects", false, "delete object creator",
  84. "delete object creator <UUID>",
  85. "Delete scene objects by creator",
  86. "Command will ask for confirmation before proceeding.",
  87. HandleDeleteObject);
  88. m_console.Commands.AddCommand(
  89. "Objects", false, "delete object id",
  90. "delete object id <UUID-or-localID>",
  91. "Delete a scene object by uuid or localID",
  92. HandleDeleteObject);
  93. m_console.Commands.AddCommand(
  94. "Objects", false, "delete object name",
  95. "delete object name [--regex] <name>",
  96. "Delete a scene object by name.",
  97. "Command will ask for confirmation before proceeding.\n"
  98. + "If --regex is specified then the name is treatead as a regular expression",
  99. HandleDeleteObject);
  100. m_console.Commands.AddCommand(
  101. "Objects", false, "delete object outside",
  102. "delete object outside",
  103. "Delete all scene objects outside region boundaries",
  104. "Command will ask for confirmation before proceeding.",
  105. HandleDeleteObject);
  106. m_console.Commands.AddCommand(
  107. "Objects",
  108. false,
  109. "delete object pos",
  110. "delete object pos <start x, start y , start z> <end x, end y, end z>",
  111. "Delete scene objects within the given volume.",
  112. ConsoleUtil.CoordHelp,
  113. HandleDeleteObject);
  114. m_console.Commands.AddCommand(
  115. "Objects",
  116. false,
  117. "show object id",
  118. "show object id [--full] <UUID-or-localID>",
  119. "Show details of a scene object with the given UUID or localID",
  120. "The --full option will print out information on all the parts of the object.\n"
  121. + "For yet more detailed part information, use the \"show part\" commands.",
  122. HandleShowObjectById);
  123. m_console.Commands.AddCommand(
  124. "Objects",
  125. false,
  126. "show object name",
  127. "show object name [--full] [--regex] <name>",
  128. "Show details of scene objects with the given name.",
  129. "The --full option will print out information on all the parts of the object.\n"
  130. + "For yet more detailed part information, use the \"show part\" commands.\n"
  131. + "If --regex is specified then the name is treatead as a regular expression.",
  132. HandleShowObjectByName);
  133. m_console.Commands.AddCommand(
  134. "Objects",
  135. false,
  136. "show object owner",
  137. "show object owner [--full] <OwnerID>",
  138. "Show details of scene objects with given owner.",
  139. "The --full option will print out information on all the parts of the object.\n",
  140. HandleShowObjectByOwnerID);
  141. m_console.Commands.AddCommand(
  142. "Objects",
  143. false,
  144. "show object pos",
  145. "show object pos [--full] <start x, start y , start z> <end x, end y, end z>",
  146. "Show details of scene objects within give volume",
  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. + ConsoleUtil.CoordHelp,
  150. HandleShowObjectByPos);
  151. m_console.Commands.AddCommand(
  152. "Objects",
  153. false,
  154. "show part id",
  155. "show part id <UUID-or-localID>",
  156. "Show details of a scene object part with the given UUID or localID", HandleShowPartById);
  157. m_console.Commands.AddCommand(
  158. "Objects",
  159. false,
  160. "show part name",
  161. "show part name [--regex] <name>",
  162. "Show details of scene object parts with the given name.",
  163. "If --regex is specified then the name is treated as a regular expression",
  164. HandleShowPartByName);
  165. m_console.Commands.AddCommand(
  166. "Objects",
  167. false,
  168. "show part pos",
  169. "show part pos <start x, start y , start z> <end x, end y, end z>",
  170. "Show details of scene object parts within the given volume.",
  171. ConsoleUtil.CoordHelp,
  172. HandleShowPartByPos);
  173. m_console.Commands.AddCommand(
  174. "Objects",
  175. false,
  176. "dump object id",
  177. "dump object id <UUID-or-localID>",
  178. "Dump the formatted serialization of the given object to the file <UUID>.xml",
  179. "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n"
  180. + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n"
  181. + "If a local ID is given then the filename used is still that for the UUID",
  182. HandleDumpObjectById);
  183. }
  184. public void RemoveRegion(Scene scene)
  185. {
  186. // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
  187. }
  188. public void RegionLoaded(Scene scene)
  189. {
  190. // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
  191. }
  192. /// <summary>
  193. /// Outputs the sogs to console.
  194. /// </summary>
  195. /// <param name='searchPredicate'></param>
  196. /// <param name='showFull'>If true then output all part details. If false then output summary.</param>
  197. private void OutputSogsToConsole(Predicate<SceneObjectGroup> searchPredicate, bool showFull)
  198. {
  199. List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate);
  200. StringBuilder sb = new StringBuilder();
  201. foreach (SceneObjectGroup so in sceneObjects)
  202. {
  203. AddSceneObjectReport(sb, so, showFull);
  204. sb.Append("\n");
  205. }
  206. sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name);
  207. m_console.Output(sb.ToString());
  208. }
  209. private void OutputSopsToConsole(Predicate<SceneObjectPart> searchPredicate, bool showFull)
  210. {
  211. List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
  212. List<SceneObjectPart> parts = new List<SceneObjectPart>();
  213. sceneObjects.ForEach(so => parts.AddRange(Array.FindAll<SceneObjectPart>(so.Parts, searchPredicate)));
  214. StringBuilder sb = new StringBuilder();
  215. foreach (SceneObjectPart part in parts)
  216. {
  217. AddScenePartReport(sb, part, showFull);
  218. sb.Append("\n");
  219. }
  220. sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name);
  221. m_console.Output(sb.ToString());
  222. }
  223. private void HandleShowObjectById(string module, string[] cmdparams)
  224. {
  225. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  226. return;
  227. bool showFull = false;
  228. OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
  229. List<string> mainParams = options.Parse(cmdparams);
  230. if (mainParams.Count < 4)
  231. {
  232. m_console.Output("Usage: show object uuid <uuid>");
  233. return;
  234. }
  235. UUID uuid;
  236. uint localId;
  237. if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId))
  238. return;
  239. SceneObjectGroup so;
  240. if (localId != ConsoleUtil.LocalIdNotFound)
  241. so = m_scene.GetSceneObjectGroup(localId);
  242. else
  243. so = m_scene.GetSceneObjectGroup(uuid);
  244. if (so == null)
  245. {
  246. // m_console.OutputFormat("No part found with uuid {0}", objectUuid);
  247. return;
  248. }
  249. StringBuilder sb = new StringBuilder();
  250. AddSceneObjectReport(sb, so, showFull);
  251. m_console.Output(sb.ToString());
  252. }
  253. private void HandleShowObjectByName(string module, string[] cmdparams)
  254. {
  255. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  256. return;
  257. bool showFull = false;
  258. bool useRegex = false;
  259. OptionSet options = new OptionSet();
  260. options.Add("full", v => showFull = v != null );
  261. options.Add("regex", v => useRegex = v != null );
  262. List<string> mainParams = options.Parse(cmdparams);
  263. if (mainParams.Count < 4)
  264. {
  265. m_console.Output("Usage: show object name [--full] [--regex] <name>");
  266. return;
  267. }
  268. string name = mainParams[3];
  269. Predicate<SceneObjectGroup> searchPredicate;
  270. if (useRegex)
  271. {
  272. Regex nameRegex = new Regex(name);
  273. searchPredicate = so => nameRegex.IsMatch(so.Name);
  274. }
  275. else
  276. {
  277. searchPredicate = so => so.Name == name;
  278. }
  279. OutputSogsToConsole(searchPredicate, showFull);
  280. }
  281. private void HandleShowObjectByOwnerID(string module, string[] cmdparams)
  282. {
  283. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  284. return;
  285. bool showFull = false;
  286. OptionSet options = new OptionSet().Add("full", v => showFull = v != null);
  287. List<string> mainParams = options.Parse(cmdparams);
  288. if (mainParams.Count < 4)
  289. {
  290. m_console.Output("Usage: show object owner <OwnerID>");
  291. return;
  292. }
  293. UUID ownerID;
  294. if (!ConsoleUtil.TryParseConsoleUuid(m_console, mainParams[3], out ownerID))
  295. return;
  296. Predicate<SceneObjectGroup> searchPredicate
  297. = so => so.OwnerID == ownerID && !so.IsAttachment;
  298. OutputSogsToConsole(searchPredicate, showFull);
  299. }
  300. private void HandleShowObjectByPos(string module, string[] cmdparams)
  301. {
  302. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  303. return;
  304. bool showFull = false;
  305. OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
  306. List<string> mainParams = options.Parse(cmdparams);
  307. if (mainParams.Count < 5)
  308. {
  309. m_console.Output("Usage: show object pos [--full] <start-coord> to <end-coord>");
  310. return;
  311. }
  312. Vector3 startVector, endVector;
  313. if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
  314. return;
  315. Predicate<SceneObjectGroup> searchPredicate
  316. = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector);
  317. OutputSogsToConsole(searchPredicate, showFull);
  318. }
  319. private void HandleShowPartById(string module, string[] cmdparams)
  320. {
  321. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  322. return;
  323. // bool showFull = false;
  324. OptionSet options = new OptionSet();
  325. // options.Add("full", v => showFull = v != null );
  326. List<string> mainParams = options.Parse(cmdparams);
  327. if (mainParams.Count < 4)
  328. {
  329. //m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>");
  330. m_console.Output("Usage: show part id <UUID-or-localID>");
  331. return;
  332. }
  333. UUID objectUuid;
  334. uint localId;
  335. if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId))
  336. return;
  337. SceneObjectPart sop;
  338. if (localId == ConsoleUtil.LocalIdNotFound)
  339. sop = m_scene.GetSceneObjectPart(objectUuid);
  340. else
  341. sop = m_scene.GetSceneObjectPart(localId);
  342. if (sop == null)
  343. {
  344. // m_console.OutputFormat("No part found with uuid {0}", objectUuid);
  345. return;
  346. }
  347. StringBuilder sb = new StringBuilder();
  348. AddScenePartReport(sb, sop, true);
  349. m_console.Output(sb.ToString());
  350. }
  351. private void HandleShowPartByPos(string module, string[] cmdparams)
  352. {
  353. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  354. return;
  355. // bool showFull = false;
  356. OptionSet options = new OptionSet();
  357. // options.Add("full", v => showFull = v != null );
  358. List<string> mainParams = options.Parse(cmdparams);
  359. if (mainParams.Count < 5)
  360. {
  361. //m_console.OutputFormat("Usage: show part pos <start-coord> to <end-coord>");
  362. m_console.Output("Usage: show part pos [--full] <start-coord> to <end-coord>");
  363. return;
  364. }
  365. string rawConsoleStartVector = mainParams[3];
  366. Vector3 startVector;
  367. if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
  368. {
  369. m_console.Output("Error: Start vector '{0}' does not have a valid format", null, rawConsoleStartVector);
  370. return;
  371. }
  372. string rawConsoleEndVector = mainParams[5];
  373. Vector3 endVector;
  374. if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
  375. {
  376. m_console.Output("Error: End vector '{0}' does not have a valid format", null, rawConsoleEndVector);
  377. return;
  378. }
  379. OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true);
  380. }
  381. private void HandleShowPartByName(string module, string[] cmdparams)
  382. {
  383. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  384. return;
  385. // bool showFull = false;
  386. bool useRegex = false;
  387. OptionSet options = new OptionSet();
  388. // options.Add("full", v => showFull = v != null );
  389. options.Add("regex", v => useRegex = v != null );
  390. List<string> mainParams = options.Parse(cmdparams);
  391. if (mainParams.Count < 4)
  392. {
  393. m_console.Output("Usage: show part name [--regex] <name>");
  394. //m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>");
  395. return;
  396. }
  397. string name = mainParams[3];
  398. Predicate<SceneObjectPart> searchPredicate;
  399. if (useRegex)
  400. {
  401. Regex nameRegex = new Regex(name);
  402. searchPredicate = sop => nameRegex.IsMatch(sop.Name);
  403. }
  404. else
  405. {
  406. searchPredicate = sop => sop.Name == name;
  407. }
  408. OutputSopsToConsole(searchPredicate, true);
  409. }
  410. private void HandleDumpObjectById(string module, string[] cmdparams)
  411. {
  412. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  413. return;
  414. if (cmdparams.Length < 4)
  415. {
  416. m_console.Output("Usage: dump object id <UUID-or-localID>");
  417. return;
  418. }
  419. UUID objectUuid;
  420. uint localId;
  421. if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId))
  422. return;
  423. SceneObjectGroup so;
  424. if (localId == ConsoleUtil.LocalIdNotFound)
  425. so = m_scene.GetSceneObjectGroup(objectUuid);
  426. else
  427. so = m_scene.GetSceneObjectGroup(localId);
  428. if (so == null)
  429. {
  430. // m_console.OutputFormat("No part found with uuid {0}", objectUuid);
  431. return;
  432. }
  433. // In case we found it via local ID.
  434. objectUuid = so.UUID;
  435. string fileName = string.Format("{0}.xml", objectUuid);
  436. if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName))
  437. return;
  438. using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8))
  439. {
  440. xtw.Formatting = Formatting.Indented;
  441. SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true);
  442. }
  443. m_console.Output("Object dumped to file {0}", fileName);
  444. }
  445. /// <summary>
  446. /// Append a scene object report to an input StringBuilder
  447. /// </summary>
  448. /// <returns></returns>
  449. /// <param name='sb'></param>
  450. /// <param name='so'</param>
  451. /// <param name='showFull'>
  452. /// If true then information on all parts of an object is appended.
  453. /// If false then only summary information about an object is appended.
  454. /// </param>
  455. private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull)
  456. {
  457. if (showFull)
  458. {
  459. foreach (SceneObjectPart sop in so.Parts)
  460. {
  461. AddScenePartReport(sb, sop, false);
  462. sb.Append("\n");
  463. }
  464. }
  465. else
  466. {
  467. AddSummarySceneObjectReport(sb, so);
  468. }
  469. return sb;
  470. }
  471. private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so)
  472. {
  473. ConsoleDisplayList cdl = new ConsoleDisplayList();
  474. cdl.AddRow("Name", so.Name);
  475. cdl.AddRow("Description", so.Description);
  476. cdl.AddRow("Local ID", so.LocalId);
  477. cdl.AddRow("UUID", so.UUID);
  478. cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
  479. cdl.AddRow("Parts", so.PrimCount);
  480. cdl.AddRow("Flags", so.RootPart.Flags);
  481. return sb.Append(cdl.ToString());
  482. }
  483. /// <summary>
  484. /// Append a scene object part report to an input StringBuilder
  485. /// </summary>
  486. /// <returns></returns>
  487. /// <param name='sb'></param>
  488. /// <param name='sop'</param>
  489. /// <param name='showFull'>
  490. /// If true then information on each inventory item will be shown.
  491. /// If false then only summary inventory information is shown.
  492. /// </param>
  493. private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull)
  494. {
  495. ConsoleDisplayList cdl = new ConsoleDisplayList();
  496. cdl.AddRow("Name", sop.Name);
  497. cdl.AddRow("Description", sop.Description);
  498. cdl.AddRow("Local ID", sop.LocalId);
  499. cdl.AddRow("UUID", sop.UUID);
  500. cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name));
  501. cdl.AddRow(
  502. "Parent",
  503. sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID));
  504. cdl.AddRow("Link number", sop.LinkNum);
  505. cdl.AddRow("Flags", sop.Flags);
  506. if (showFull)
  507. {
  508. PrimitiveBaseShape s = sop.Shape;
  509. cdl.AddRow("FlexiDrag", s.FlexiDrag);
  510. cdl.AddRow("FlexiEntry", s.FlexiEntry);
  511. cdl.AddRow("FlexiForce", string.Format("<{0},{1},{2}>", s.FlexiForceX, s.FlexiForceY, s.FlexiForceZ));
  512. cdl.AddRow("FlexiGravity", s.FlexiGravity);
  513. cdl.AddRow("FlexiSoftness", s.FlexiSoftness);
  514. cdl.AddRow("HollowShape", s.HollowShape);
  515. cdl.AddRow(
  516. "LightColor",
  517. string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA));
  518. cdl.AddRow("LightCutoff", s.LightCutoff);
  519. cdl.AddRow("LightEntry", s.LightEntry);
  520. cdl.AddRow("LightFalloff", s.LightFalloff);
  521. cdl.AddRow("LightIntensity", s.LightIntensity);
  522. cdl.AddRow("LightRadius", s.LightRadius);
  523. cdl.AddRow("Location (relative)", sop.RelativePosition);
  524. cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a"));
  525. cdl.AddRow("PathBegin", s.PathBegin);
  526. cdl.AddRow("PathEnd", s.PathEnd);
  527. cdl.AddRow("PathCurve", s.PathCurve);
  528. cdl.AddRow("PathRadiusOffset", s.PathRadiusOffset);
  529. cdl.AddRow("PathRevolutions", s.PathRevolutions);
  530. cdl.AddRow("PathScale", string.Format("<{0},{1}>", s.PathScaleX, s.PathScaleY));
  531. cdl.AddRow("PathSkew", string.Format("<{0},{1}>", s.PathShearX, s.PathShearY));
  532. cdl.AddRow("FlexiDrag", s.PathSkew);
  533. cdl.AddRow("PathTaper", string.Format("<{0},{1}>", s.PathTaperX, s.PathTaperY));
  534. cdl.AddRow("PathTwist", s.PathTwist);
  535. cdl.AddRow("PathTwistBegin", s.PathTwistBegin);
  536. cdl.AddRow("PCode", s.PCode);
  537. cdl.AddRow("ProfileBegin", s.ProfileBegin);
  538. cdl.AddRow("ProfileEnd", s.ProfileEnd);
  539. cdl.AddRow("ProfileHollow", s.ProfileHollow);
  540. cdl.AddRow("ProfileShape", s.ProfileShape);
  541. cdl.AddRow("ProjectionAmbiance", s.ProjectionAmbiance);
  542. cdl.AddRow("ProjectionEntry", s.ProjectionEntry);
  543. cdl.AddRow("ProjectionFocus", s.ProjectionFocus);
  544. cdl.AddRow("ProjectionFOV", s.ProjectionFOV);
  545. cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID);
  546. cdl.AddRow("Rotation (Relative)", sop.RotationOffset);
  547. cdl.AddRow("Rotation (World)", sop.GetWorldRotation());
  548. cdl.AddRow("Scale", s.Scale);
  549. cdl.AddRow(
  550. "SculptData",
  551. string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a"));
  552. cdl.AddRow("SculptEntry", s.SculptEntry);
  553. cdl.AddRow("SculptTexture", s.SculptTexture);
  554. cdl.AddRow("SculptType", s.SculptType);
  555. cdl.AddRow("State", s.State);
  556. // TODO, need to display more information about textures but in a compact format
  557. // to stop output becoming huge.
  558. for (int i = 0; i < sop.GetNumberOfSides(); i++)
  559. {
  560. Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i];
  561. UUID textureID;
  562. if (teFace != null)
  563. textureID = teFace.TextureID;
  564. else
  565. textureID = s.Textures.DefaultTexture.TextureID;
  566. cdl.AddRow(string.Format("Face {0} texture ID", i), textureID);
  567. }
  568. //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures.
  569. }
  570. object itemsOutput;
  571. if (showFull)
  572. {
  573. StringBuilder itemsSb = new StringBuilder("\n");
  574. itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString();
  575. }
  576. else
  577. {
  578. itemsOutput = sop.Inventory.Count;
  579. }
  580. cdl.AddRow("Items", itemsOutput);
  581. return sb.Append(cdl.ToString());
  582. }
  583. private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv)
  584. {
  585. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  586. cdt.Indent = 2;
  587. cdt.AddColumn("Name", 50);
  588. cdt.AddColumn("Type", 12);
  589. cdt.AddColumn("Running", 7);
  590. cdt.AddColumn("Item UUID", 36);
  591. cdt.AddColumn("Asset UUID", 36);
  592. foreach (TaskInventoryItem item in inv.GetInventoryItems())
  593. {
  594. bool foundScriptInstance, scriptRunning;
  595. foundScriptInstance
  596. = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning);
  597. cdt.AddRow(
  598. item.Name,
  599. ((InventoryType)item.InvType).ToString(),
  600. foundScriptInstance ? scriptRunning.ToString() : "n/a",
  601. item.ItemID.ToString(),
  602. item.AssetID.ToString());
  603. }
  604. return sb.Append(cdt.ToString());
  605. }
  606. private void HandleDeleteObject(string module, string[] cmd)
  607. {
  608. if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
  609. return;
  610. if (cmd.Length < 3)
  611. return;
  612. string mode = cmd[2];
  613. string o = "";
  614. if (mode != "outside")
  615. {
  616. if (cmd.Length < 4)
  617. return;
  618. o = cmd[3];
  619. }
  620. List<SceneObjectGroup> deletes = null;
  621. UUID match;
  622. bool requireConfirmation = true;
  623. switch (mode)
  624. {
  625. case "owner":
  626. if (!UUID.TryParse(o, out match))
  627. return;
  628. deletes = new List<SceneObjectGroup>();
  629. m_scene.ForEachSOG(delegate (SceneObjectGroup g)
  630. {
  631. if (g.OwnerID == match && !g.IsAttachment)
  632. deletes.Add(g);
  633. });
  634. // if (deletes.Count == 0)
  635. // m_console.OutputFormat("No objects were found with owner {0}", match);
  636. break;
  637. case "creator":
  638. if (!UUID.TryParse(o, out match))
  639. return;
  640. deletes = new List<SceneObjectGroup>();
  641. m_scene.ForEachSOG(delegate (SceneObjectGroup g)
  642. {
  643. if (g.RootPart.CreatorID == match && !g.IsAttachment)
  644. deletes.Add(g);
  645. });
  646. // if (deletes.Count == 0)
  647. // m_console.OutputFormat("No objects were found with creator {0}", match);
  648. break;
  649. case "id":
  650. UUID uuid;
  651. uint localId;
  652. if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId))
  653. return;
  654. requireConfirmation = false;
  655. deletes = new List<SceneObjectGroup>();
  656. SceneObjectGroup so;
  657. if (localId == ConsoleUtil.LocalIdNotFound)
  658. so = m_scene.GetSceneObjectGroup(uuid);
  659. else
  660. so = m_scene.GetSceneObjectGroup(localId);
  661. if (so!= null)
  662. {
  663. deletes.Add(so);
  664. if(so.IsAttachment)
  665. {
  666. requireConfirmation = true;
  667. m_console.Output("Warning: object with uuid {0} is a attachment", null, uuid);
  668. }
  669. }
  670. break;
  671. case "name":
  672. deletes = GetDeleteCandidatesByName(module, cmd);
  673. break;
  674. case "outside":
  675. deletes = new List<SceneObjectGroup>();
  676. m_scene.ForEachSOG(delegate (SceneObjectGroup g)
  677. {
  678. SceneObjectPart rootPart = g.RootPart;
  679. bool delete = false;
  680. if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0)
  681. {
  682. delete = true;
  683. }
  684. else
  685. {
  686. ILandObject parcel
  687. = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y);
  688. if (parcel == null || parcel.LandData.Name == "NO LAND")
  689. delete = true;
  690. }
  691. if (delete && !g.IsAttachment && !deletes.Contains(g))
  692. deletes.Add(g);
  693. });
  694. if (deletes.Count == 0)
  695. m_console.Output("No objects were found outside region bounds");
  696. break;
  697. case "pos":
  698. deletes = GetDeleteCandidatesByPos(module, cmd);
  699. break;
  700. default:
  701. m_console.Output("Unrecognized mode {0}", null, mode);
  702. return;
  703. }
  704. if (deletes == null || deletes.Count <= 0)
  705. return;
  706. if (requireConfirmation)
  707. {
  708. string response = MainConsole.Instance.Prompt(
  709. string.Format(
  710. "Are you sure that you want to delete {0} objects from {1}",
  711. deletes.Count, m_scene.RegionInfo.RegionName),
  712. "y/N");
  713. if (response.ToLower() != "y")
  714. {
  715. MainConsole.Instance.Output(
  716. "Aborting delete of {0} objects from {1}", null, deletes.Count, m_scene.RegionInfo.RegionName);
  717. return;
  718. }
  719. }
  720. m_console.Output("Deleting {0} objects in {1}", null, deletes.Count, m_scene.RegionInfo.RegionName);
  721. foreach (SceneObjectGroup g in deletes)
  722. {
  723. m_console.Output("Deleting object {0} {1}", null, g.UUID, g.Name);
  724. m_scene.DeleteSceneObject(g, false);
  725. }
  726. }
  727. private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
  728. {
  729. bool useRegex = false;
  730. OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
  731. List<string> mainParams = options.Parse(cmdparams);
  732. if (mainParams.Count < 4)
  733. {
  734. m_console.Output("Usage: delete object name [--regex] <name>");
  735. return null;
  736. }
  737. string name = mainParams[3];
  738. List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
  739. Action<SceneObjectGroup> searchAction;
  740. if (useRegex)
  741. {
  742. Regex nameRegex = new Regex(name);
  743. searchAction = so => { if (nameRegex.IsMatch(so.Name)) {if(!so.IsAttachment) sceneObjects.Add(so);}};
  744. }
  745. else
  746. {
  747. searchAction = so => { if (so.Name == name) {if(!so.IsAttachment) sceneObjects.Add(so);}};
  748. }
  749. m_scene.ForEachSOG(searchAction);
  750. if (sceneObjects.Count == 0)
  751. m_console.Output("No objects with name {0} found in {1}", null, name, m_scene.RegionInfo.RegionName);
  752. return sceneObjects;
  753. }
  754. /// <summary>
  755. /// Get scene object delete candidates by position
  756. /// </summary>
  757. /// <param name='module'></param>
  758. /// <param name='cmdparams'></param>
  759. /// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there
  760. /// are no objects to delete then the list will be empty./returns>
  761. private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams)
  762. {
  763. if (cmdparams.Length < 5)
  764. {
  765. m_console.Output("Usage: delete object pos <start-coord> to <end-coord>");
  766. return null;
  767. }
  768. Vector3 startVector, endVector;
  769. if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
  770. return null;
  771. return m_scene.GetSceneObjectGroups().FindAll(
  772. so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector));
  773. }
  774. private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector)
  775. {
  776. string rawConsoleStartVector = rawComponents.Take(1).Single();
  777. if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
  778. {
  779. m_console.Output("Error: Start vector '{0}' does not have a valid format", null, rawConsoleStartVector);
  780. endVector = Vector3.Zero;
  781. return false;
  782. }
  783. string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
  784. if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
  785. {
  786. m_console.Output("Error: End vector '{0}' does not have a valid format", null, rawConsoleEndVector);
  787. return false;
  788. }
  789. return true;
  790. }
  791. }
  792. }