ObjectCommandsModule.cs 35 KB

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