OpenSim.cs 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  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;
  29. using System.Collections.Generic;
  30. using System.Diagnostics;
  31. using System.IO;
  32. using System.Linq;
  33. using System.Reflection;
  34. using System.Text;
  35. using System.Text.RegularExpressions;
  36. using System.Timers;
  37. using log4net;
  38. using NDesk.Options;
  39. using Nini.Config;
  40. using OpenMetaverse;
  41. using OpenSim.Framework;
  42. using OpenSim.Framework.Console;
  43. using OpenSim.Framework.Servers;
  44. using OpenSim.Framework.Monitoring;
  45. using OpenSim.Region.Framework.Interfaces;
  46. using OpenSim.Region.Framework.Scenes;
  47. namespace OpenSim
  48. {
  49. /// <summary>
  50. /// Interactive OpenSim region server
  51. /// </summary>
  52. public class OpenSim : OpenSimBase
  53. {
  54. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  55. protected string m_startupCommandsFile;
  56. protected string m_shutdownCommandsFile;
  57. protected bool m_gui = false;
  58. protected string m_consoleType = "local";
  59. protected uint m_consolePort = 0;
  60. /// <summary>
  61. /// Prompt to use for simulator command line.
  62. /// </summary>
  63. private string m_consolePrompt;
  64. /// <summary>
  65. /// Regex for parsing out special characters in the prompt.
  66. /// </summary>
  67. private Regex m_consolePromptRegex = new Regex(@"([^\\])\\(\w)", RegexOptions.Compiled);
  68. private string m_timedScript = "disabled";
  69. private int m_timeInterval = 1200;
  70. private Timer m_scriptTimer;
  71. public OpenSim(IConfigSource configSource) : base(configSource)
  72. {
  73. }
  74. protected override void ReadExtraConfigSettings()
  75. {
  76. base.ReadExtraConfigSettings();
  77. IConfig startupConfig = Config.Configs["Startup"];
  78. IConfig networkConfig = Config.Configs["Network"];
  79. int stpMinThreads = 2;
  80. int stpMaxThreads = 15;
  81. if (startupConfig != null)
  82. {
  83. m_startupCommandsFile = startupConfig.GetString("startup_console_commands_file", "startup_commands.txt");
  84. m_shutdownCommandsFile = startupConfig.GetString("shutdown_console_commands_file", "shutdown_commands.txt");
  85. if (startupConfig.GetString("console", String.Empty) == String.Empty)
  86. m_gui = startupConfig.GetBoolean("gui", false);
  87. else
  88. m_consoleType= startupConfig.GetString("console", String.Empty);
  89. if (networkConfig != null)
  90. m_consolePort = (uint)networkConfig.GetInt("console_port", 0);
  91. m_timedScript = startupConfig.GetString("timer_Script", "disabled");
  92. if (m_timedScript != "disabled")
  93. {
  94. m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
  95. }
  96. string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty);
  97. FireAndForgetMethod asyncCallMethod;
  98. if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
  99. Util.FireAndForgetMethod = asyncCallMethod;
  100. stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15);
  101. stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15);
  102. m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
  103. }
  104. if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
  105. Util.InitThreadPool(stpMinThreads, stpMaxThreads);
  106. m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
  107. }
  108. /// <summary>
  109. /// Performs initialisation of the scene, such as loading configuration from disk.
  110. /// </summary>
  111. protected override void StartupSpecific()
  112. {
  113. m_log.Info("====================================================================");
  114. m_log.Info("========================= STARTING OPENSIM =========================");
  115. m_log.Info("====================================================================");
  116. //m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString());
  117. // http://msdn.microsoft.com/en-us/library/bb384202.aspx
  118. //GCSettings.LatencyMode = GCLatencyMode.Batch;
  119. //m_log.InfoFormat("[OPENSIM MAIN]: GC Latency Mode: {0}", GCSettings.LatencyMode.ToString());
  120. if (m_gui) // Driven by external GUI
  121. {
  122. m_console = new CommandConsole("Region");
  123. }
  124. else
  125. {
  126. switch (m_consoleType)
  127. {
  128. case "basic":
  129. m_console = new CommandConsole("Region");
  130. break;
  131. case "rest":
  132. m_console = new RemoteConsole("Region");
  133. ((RemoteConsole)m_console).ReadConfig(Config);
  134. break;
  135. default:
  136. m_console = new LocalConsole("Region");
  137. break;
  138. }
  139. }
  140. MainConsole.Instance = m_console;
  141. LogEnvironmentInformation();
  142. RegisterCommonAppenders(Config.Configs["Startup"]);
  143. RegisterConsoleCommands();
  144. base.StartupSpecific();
  145. MainServer.Instance.AddStreamHandler(new OpenSim.SimStatusHandler());
  146. MainServer.Instance.AddStreamHandler(new OpenSim.XSimStatusHandler(this));
  147. if (userStatsURI != String.Empty)
  148. MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
  149. if (managedStatsURI != String.Empty)
  150. {
  151. string urlBase = String.Format("/{0}/", managedStatsURI);
  152. MainServer.Instance.AddHTTPHandler(urlBase, StatsManager.HandleStatsRequest);
  153. m_log.InfoFormat("[OPENSIM] Enabling remote managed stats fetch. URL = {0}", urlBase);
  154. }
  155. if (m_console is RemoteConsole)
  156. {
  157. if (m_consolePort == 0)
  158. {
  159. ((RemoteConsole)m_console).SetServer(m_httpServer);
  160. }
  161. else
  162. {
  163. ((RemoteConsole)m_console).SetServer(MainServer.GetHttpServer(m_consolePort));
  164. }
  165. }
  166. // Hook up to the watchdog timer
  167. Watchdog.OnWatchdogTimeout += WatchdogTimeoutHandler;
  168. PrintFileToConsole("startuplogo.txt");
  169. // For now, start at the 'root' level by default
  170. if (SceneManager.Scenes.Count == 1) // If there is only one region, select it
  171. ChangeSelectedRegion("region",
  172. new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName});
  173. else
  174. ChangeSelectedRegion("region", new string[] {"change", "region", "root"});
  175. //Run Startup Commands
  176. if (String.IsNullOrEmpty(m_startupCommandsFile))
  177. {
  178. m_log.Info("[STARTUP]: No startup command script specified. Moving on...");
  179. }
  180. else
  181. {
  182. RunCommandScript(m_startupCommandsFile);
  183. }
  184. // Start timer script (run a script every xx seconds)
  185. if (m_timedScript != "disabled")
  186. {
  187. m_scriptTimer = new Timer();
  188. m_scriptTimer.Enabled = true;
  189. m_scriptTimer.Interval = m_timeInterval*1000;
  190. m_scriptTimer.Elapsed += RunAutoTimerScript;
  191. }
  192. }
  193. /// <summary>
  194. /// Register standard set of region console commands
  195. /// </summary>
  196. private void RegisterConsoleCommands()
  197. {
  198. MainServer.RegisterHttpConsoleCommands(m_console);
  199. m_console.Commands.AddCommand("Objects", false, "force update",
  200. "force update",
  201. "Force the update of all objects on clients",
  202. HandleForceUpdate);
  203. m_console.Commands.AddCommand("General", false, "change region",
  204. "change region <region name>",
  205. "Change current console region",
  206. ChangeSelectedRegion);
  207. m_console.Commands.AddCommand("Archiving", false, "save xml",
  208. "save xml",
  209. "Save a region's data in XML format",
  210. SaveXml);
  211. m_console.Commands.AddCommand("Archiving", false, "save xml2",
  212. "save xml2",
  213. "Save a region's data in XML2 format",
  214. SaveXml2);
  215. m_console.Commands.AddCommand("Archiving", false, "load xml",
  216. "load xml [-newIDs [<x> <y> <z>]]",
  217. "Load a region's data from XML format",
  218. LoadXml);
  219. m_console.Commands.AddCommand("Archiving", false, "load xml2",
  220. "load xml2",
  221. "Load a region's data from XML2 format",
  222. LoadXml2);
  223. m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
  224. "save prims xml2 [<prim name> <file name>]",
  225. "Save named prim to XML2",
  226. SavePrimsXml2);
  227. m_console.Commands.AddCommand("Archiving", false, "load oar",
  228. "load oar [--merge] [--skip-assets] [<OAR path>]",
  229. "Load a region's data from an OAR archive.",
  230. "--merge will merge the OAR with the existing scene." + Environment.NewLine
  231. + "--skip-assets will load the OAR but ignore the assets it contains." + Environment.NewLine
  232. + "The path can be either a filesystem location or a URI."
  233. + " If this is not given then the command looks for an OAR named region.oar in the current directory.",
  234. LoadOar);
  235. m_console.Commands.AddCommand("Archiving", false, "save oar",
  236. //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
  237. "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]",
  238. "Save a region's data to an OAR archive.",
  239. // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
  240. "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
  241. + "--noassets stops assets being saved to the OAR.\n"
  242. + "--publish saves an OAR stripped of owner and last owner information.\n"
  243. + " on reload, the estate owner will be the owner of all objects\n"
  244. + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
  245. + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
  246. + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
  247. + "--all saves all the regions in the simulator, instead of just the current region.\n"
  248. + "The OAR path must be a filesystem path."
  249. + " If this is not given then the oar is saved to region.oar in the current directory.",
  250. SaveOar);
  251. m_console.Commands.AddCommand("Objects", false, "edit scale",
  252. "edit scale <name> <x> <y> <z>",
  253. "Change the scale of a named prim",
  254. HandleEditScale);
  255. m_console.Commands.AddCommand("Users", false, "kick user",
  256. "kick user <first> <last> [--force] [message]",
  257. "Kick a user off the simulator",
  258. "The --force option will kick the user without any checks to see whether it's already in the process of closing\n"
  259. + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them",
  260. KickUserCommand);
  261. m_console.Commands.AddCommand("Users", false, "show users",
  262. "show users [full]",
  263. "Show user data for users currently on the region",
  264. "Without the 'full' option, only users actually on the region are shown."
  265. + " With the 'full' option child agents of users in neighbouring regions are also shown.",
  266. HandleShow);
  267. m_console.Commands.AddCommand("Comms", false, "show connections",
  268. "show connections",
  269. "Show connection data",
  270. HandleShow);
  271. m_console.Commands.AddCommand("Comms", false, "show circuits",
  272. "show circuits",
  273. "Show agent circuit data",
  274. HandleShow);
  275. m_console.Commands.AddCommand("Comms", false, "show pending-objects",
  276. "show pending-objects",
  277. "Show # of objects on the pending queues of all scene viewers",
  278. HandleShow);
  279. m_console.Commands.AddCommand("General", false, "show modules",
  280. "show modules",
  281. "Show module data",
  282. HandleShow);
  283. m_console.Commands.AddCommand("Regions", false, "show regions",
  284. "show regions",
  285. "Show region data",
  286. HandleShow);
  287. m_console.Commands.AddCommand("Regions", false, "show ratings",
  288. "show ratings",
  289. "Show rating data",
  290. HandleShow);
  291. m_console.Commands.AddCommand("Objects", false, "backup",
  292. "backup",
  293. "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.",
  294. RunCommand);
  295. m_console.Commands.AddCommand("Regions", false, "create region",
  296. "create region [\"region name\"] <region_file.ini>",
  297. "Create a new region.",
  298. "The settings for \"region name\" are read from <region_file.ini>. Paths specified with <region_file.ini> are relative to your Regions directory, unless an absolute path is given."
  299. + " If \"region name\" does not exist in <region_file.ini>, it will be added." + Environment.NewLine
  300. + "Without \"region name\", the first region found in <region_file.ini> will be created." + Environment.NewLine
  301. + "If <region_file.ini> does not exist, it will be created.",
  302. HandleCreateRegion);
  303. m_console.Commands.AddCommand("Regions", false, "restart",
  304. "restart",
  305. "Restart all sims in this instance",
  306. RunCommand);
  307. m_console.Commands.AddCommand("General", false, "command-script",
  308. "command-script <script>",
  309. "Run a command script from file",
  310. RunCommand);
  311. m_console.Commands.AddCommand("Regions", false, "remove-region",
  312. "remove-region <name>",
  313. "Remove a region from this simulator",
  314. RunCommand);
  315. m_console.Commands.AddCommand("Regions", false, "delete-region",
  316. "delete-region <name>",
  317. "Delete a region from disk",
  318. RunCommand);
  319. }
  320. protected override void ShutdownSpecific()
  321. {
  322. if (m_shutdownCommandsFile != String.Empty)
  323. {
  324. RunCommandScript(m_shutdownCommandsFile);
  325. }
  326. base.ShutdownSpecific();
  327. }
  328. /// <summary>
  329. /// Timer to run a specific text file as console commands. Configured in in the main ini file
  330. /// </summary>
  331. /// <param name="sender"></param>
  332. /// <param name="e"></param>
  333. private void RunAutoTimerScript(object sender, EventArgs e)
  334. {
  335. if (m_timedScript != "disabled")
  336. {
  337. RunCommandScript(m_timedScript);
  338. }
  339. }
  340. private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi)
  341. {
  342. int now = Environment.TickCount & Int32.MaxValue;
  343. m_log.ErrorFormat(
  344. "[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}",
  345. twi.Thread.Name,
  346. twi.Thread.ThreadState,
  347. now - twi.LastTick,
  348. twi.AlarmMethod != null ? string.Format("Data: {0}", twi.AlarmMethod()) : "");
  349. }
  350. #region Console Commands
  351. /// <summary>
  352. /// Kicks users off the region
  353. /// </summary>
  354. /// <param name="module"></param>
  355. /// <param name="cmdparams">name of avatar to kick</param>
  356. private void KickUserCommand(string module, string[] cmdparams)
  357. {
  358. bool force = false;
  359. OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; });
  360. List<string> mainParams = options.Parse(cmdparams);
  361. if (mainParams.Count < 4)
  362. return;
  363. string alert = null;
  364. if (mainParams.Count > 4)
  365. alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
  366. IList agents = SceneManager.GetCurrentSceneAvatars();
  367. foreach (ScenePresence presence in agents)
  368. {
  369. RegionInfo regionInfo = presence.Scene.RegionInfo;
  370. if (presence.Firstname.ToLower().Equals(mainParams[2].ToLower()) &&
  371. presence.Lastname.ToLower().Equals(mainParams[3].ToLower()))
  372. {
  373. MainConsole.Instance.Output(
  374. String.Format(
  375. "Kicking user: {0,-16} {1,-16} {2,-37} in region: {3,-16}",
  376. presence.Firstname, presence.Lastname, presence.UUID, regionInfo.RegionName));
  377. // kick client...
  378. if (alert != null)
  379. presence.ControllingClient.Kick(alert);
  380. else
  381. presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
  382. presence.Scene.CloseAgent(presence.UUID, force);
  383. break;
  384. }
  385. }
  386. MainConsole.Instance.Output("");
  387. }
  388. /// <summary>
  389. /// Opens a file and uses it as input to the console command parser.
  390. /// </summary>
  391. /// <param name="fileName">name of file to use as input to the console</param>
  392. private static void PrintFileToConsole(string fileName)
  393. {
  394. if (File.Exists(fileName))
  395. {
  396. StreamReader readFile = File.OpenText(fileName);
  397. string currentLine;
  398. while ((currentLine = readFile.ReadLine()) != null)
  399. {
  400. m_log.Info("[!]" + currentLine);
  401. }
  402. }
  403. }
  404. /// <summary>
  405. /// Force resending of all updates to all clients in active region(s)
  406. /// </summary>
  407. /// <param name="module"></param>
  408. /// <param name="args"></param>
  409. private void HandleForceUpdate(string module, string[] args)
  410. {
  411. MainConsole.Instance.Output("Updating all clients");
  412. SceneManager.ForceCurrentSceneClientUpdate();
  413. }
  414. /// <summary>
  415. /// Edits the scale of a primative with the name specified
  416. /// </summary>
  417. /// <param name="module"></param>
  418. /// <param name="args">0,1, name, x, y, z</param>
  419. private void HandleEditScale(string module, string[] args)
  420. {
  421. if (args.Length == 6)
  422. {
  423. SceneManager.HandleEditCommandOnCurrentScene(args);
  424. }
  425. else
  426. {
  427. MainConsole.Instance.Output("Argument error: edit scale <prim name> <x> <y> <z>");
  428. }
  429. }
  430. /// <summary>
  431. /// Creates a new region based on the parameters specified. This will ask the user questions on the console
  432. /// </summary>
  433. /// <param name="module"></param>
  434. /// <param name="cmd">0,1,region name, region ini or XML file</param>
  435. private void HandleCreateRegion(string module, string[] cmd)
  436. {
  437. string regionName = string.Empty;
  438. string regionFile = string.Empty;
  439. if (cmd.Length == 3)
  440. {
  441. regionFile = cmd[2];
  442. }
  443. else if (cmd.Length > 3)
  444. {
  445. regionName = cmd[2];
  446. regionFile = cmd[3];
  447. }
  448. string extension = Path.GetExtension(regionFile).ToLower();
  449. bool isXml = extension.Equals(".xml");
  450. bool isIni = extension.Equals(".ini");
  451. if (!isXml && !isIni)
  452. {
  453. MainConsole.Instance.Output("Usage: create region [\"region name\"] <region_file.ini>");
  454. return;
  455. }
  456. if (!Path.IsPathRooted(regionFile))
  457. {
  458. string regionsDir = ConfigSource.Source.Configs["Startup"].GetString("regionload_regionsdir", "Regions").Trim();
  459. regionFile = Path.Combine(regionsDir, regionFile);
  460. }
  461. RegionInfo regInfo;
  462. if (isXml)
  463. {
  464. regInfo = new RegionInfo(regionName, regionFile, false, ConfigSource.Source);
  465. }
  466. else
  467. {
  468. regInfo = new RegionInfo(regionName, regionFile, false, ConfigSource.Source, regionName);
  469. }
  470. Scene existingScene;
  471. if (SceneManager.TryGetScene(regInfo.RegionID, out existingScene))
  472. {
  473. MainConsole.Instance.OutputFormat(
  474. "ERROR: Cannot create region {0} with ID {1}, this ID is already assigned to region {2}",
  475. regInfo.RegionName, regInfo.RegionID, existingScene.RegionInfo.RegionName);
  476. return;
  477. }
  478. bool changed = PopulateRegionEstateInfo(regInfo);
  479. IScene scene;
  480. CreateRegion(regInfo, true, out scene);
  481. if (changed)
  482. regInfo.EstateSettings.Save();
  483. }
  484. /// <summary>
  485. /// Runs commands issued by the server console from the operator
  486. /// </summary>
  487. /// <param name="command">The first argument of the parameter (the command)</param>
  488. /// <param name="cmdparams">Additional arguments passed to the command</param>
  489. public void RunCommand(string module, string[] cmdparams)
  490. {
  491. List<string> args = new List<string>(cmdparams);
  492. if (args.Count < 1)
  493. return;
  494. string command = args[0];
  495. args.RemoveAt(0);
  496. cmdparams = args.ToArray();
  497. switch (command)
  498. {
  499. case "backup":
  500. MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
  501. SceneManager.BackupCurrentScene();
  502. break;
  503. case "remove-region":
  504. string regRemoveName = CombineParams(cmdparams, 0);
  505. Scene removeScene;
  506. if (SceneManager.TryGetScene(regRemoveName, out removeScene))
  507. RemoveRegion(removeScene, false);
  508. else
  509. MainConsole.Instance.Output("No region with that name");
  510. break;
  511. case "delete-region":
  512. string regDeleteName = CombineParams(cmdparams, 0);
  513. Scene killScene;
  514. if (SceneManager.TryGetScene(regDeleteName, out killScene))
  515. RemoveRegion(killScene, true);
  516. else
  517. MainConsole.Instance.Output("no region with that name");
  518. break;
  519. case "restart":
  520. SceneManager.RestartCurrentScene();
  521. break;
  522. }
  523. }
  524. /// <summary>
  525. /// Change the currently selected region. The selected region is that operated upon by single region commands.
  526. /// </summary>
  527. /// <param name="cmdParams"></param>
  528. protected void ChangeSelectedRegion(string module, string[] cmdparams)
  529. {
  530. if (cmdparams.Length > 2)
  531. {
  532. string newRegionName = CombineParams(cmdparams, 2);
  533. if (!SceneManager.TrySetCurrentScene(newRegionName))
  534. MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
  535. else
  536. RefreshPrompt();
  537. }
  538. else
  539. {
  540. MainConsole.Instance.Output("Usage: change region <region name>");
  541. }
  542. }
  543. /// <summary>
  544. /// Refreshs prompt with the current selection details.
  545. /// </summary>
  546. private void RefreshPrompt()
  547. {
  548. string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
  549. MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
  550. // m_log.DebugFormat("Original prompt is {0}", m_consolePrompt);
  551. string prompt = m_consolePrompt;
  552. // Replace "\R" with the region name
  553. // Replace "\\" with "\"
  554. prompt = m_consolePromptRegex.Replace(prompt, m =>
  555. {
  556. // m_log.DebugFormat("Matched {0}", m.Groups[2].Value);
  557. if (m.Groups[2].Value == "R")
  558. return m.Groups[1].Value + regionName;
  559. else
  560. return m.Groups[0].Value;
  561. });
  562. m_console.DefaultPrompt = prompt;
  563. m_console.ConsoleScene = SceneManager.CurrentScene;
  564. }
  565. protected override void HandleRestartRegion(RegionInfo whichRegion)
  566. {
  567. base.HandleRestartRegion(whichRegion);
  568. // Where we are restarting multiple scenes at once, a previous call to RefreshPrompt may have set the
  569. // m_console.ConsoleScene to null (indicating all scenes).
  570. if (m_console.ConsoleScene != null && whichRegion.RegionName == ((Scene)m_console.ConsoleScene).Name)
  571. SceneManager.TrySetCurrentScene(whichRegion.RegionName);
  572. RefreshPrompt();
  573. }
  574. // see BaseOpenSimServer
  575. /// <summary>
  576. /// Many commands list objects for debugging. Some of the types are listed here
  577. /// </summary>
  578. /// <param name="mod"></param>
  579. /// <param name="cmd"></param>
  580. public override void HandleShow(string mod, string[] cmd)
  581. {
  582. base.HandleShow(mod, cmd);
  583. List<string> args = new List<string>(cmd);
  584. args.RemoveAt(0);
  585. string[] showParams = args.ToArray();
  586. switch (showParams[0])
  587. {
  588. case "users":
  589. IList agents;
  590. if (showParams.Length > 1 && showParams[1] == "full")
  591. {
  592. agents = SceneManager.GetCurrentScenePresences();
  593. } else
  594. {
  595. agents = SceneManager.GetCurrentSceneAvatars();
  596. }
  597. MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count));
  598. MainConsole.Instance.Output(
  599. String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname",
  600. "Agent ID", "Root/Child", "Region", "Position")
  601. );
  602. foreach (ScenePresence presence in agents)
  603. {
  604. RegionInfo regionInfo = presence.Scene.RegionInfo;
  605. string regionName;
  606. if (regionInfo == null)
  607. {
  608. regionName = "Unresolvable";
  609. } else
  610. {
  611. regionName = regionInfo.RegionName;
  612. }
  613. MainConsole.Instance.Output(
  614. String.Format(
  615. "{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}",
  616. presence.Firstname,
  617. presence.Lastname,
  618. presence.UUID,
  619. presence.IsChildAgent ? "Child" : "Root",
  620. regionName,
  621. presence.AbsolutePosition.ToString())
  622. );
  623. }
  624. MainConsole.Instance.Output(String.Empty);
  625. break;
  626. case "connections":
  627. HandleShowConnections();
  628. break;
  629. case "circuits":
  630. HandleShowCircuits();
  631. break;
  632. case "modules":
  633. SceneManager.ForEachSelectedScene(
  634. scene =>
  635. {
  636. MainConsole.Instance.OutputFormat("Loaded region modules in {0} are:", scene.Name);
  637. List<IRegionModuleBase> sharedModules = new List<IRegionModuleBase>();
  638. List<IRegionModuleBase> nonSharedModules = new List<IRegionModuleBase>();
  639. foreach (IRegionModuleBase module in scene.RegionModules.Values)
  640. {
  641. if (module.GetType().GetInterface("ISharedRegionModule") != null)
  642. nonSharedModules.Add(module);
  643. else
  644. sharedModules.Add(module);
  645. }
  646. foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name))
  647. MainConsole.Instance.OutputFormat("New Region Module (Shared): {0}", module.Name);
  648. foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name))
  649. MainConsole.Instance.OutputFormat("New Region Module (Non-Shared): {0}", module.Name);
  650. }
  651. );
  652. MainConsole.Instance.Output("");
  653. break;
  654. case "regions":
  655. SceneManager.ForEachScene(
  656. delegate(Scene scene)
  657. {
  658. MainConsole.Instance.Output(String.Format(
  659. "Region Name: {0}, Region XLoc: {1}, Region YLoc: {2}, Region Port: {3}, Estate Name: {4}",
  660. scene.RegionInfo.RegionName,
  661. scene.RegionInfo.RegionLocX,
  662. scene.RegionInfo.RegionLocY,
  663. scene.RegionInfo.InternalEndPoint.Port,
  664. scene.RegionInfo.EstateSettings.EstateName));
  665. });
  666. break;
  667. case "ratings":
  668. SceneManager.ForEachScene(
  669. delegate(Scene scene)
  670. {
  671. string rating = "";
  672. if (scene.RegionInfo.RegionSettings.Maturity == 1)
  673. {
  674. rating = "MATURE";
  675. }
  676. else if (scene.RegionInfo.RegionSettings.Maturity == 2)
  677. {
  678. rating = "ADULT";
  679. }
  680. else
  681. {
  682. rating = "PG";
  683. }
  684. MainConsole.Instance.Output(String.Format(
  685. "Region Name: {0}, Region Rating {1}",
  686. scene.RegionInfo.RegionName,
  687. rating));
  688. });
  689. break;
  690. }
  691. }
  692. private void HandleShowCircuits()
  693. {
  694. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  695. cdt.AddColumn("Region", 20);
  696. cdt.AddColumn("Avatar name", 24);
  697. cdt.AddColumn("Type", 5);
  698. cdt.AddColumn("Code", 10);
  699. cdt.AddColumn("IP", 16);
  700. cdt.AddColumn("Viewer Name", 24);
  701. SceneManager.ForEachScene(
  702. s =>
  703. {
  704. foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
  705. cdt.AddRow(
  706. s.Name,
  707. aCircuit.Name,
  708. aCircuit.child ? "child" : "root",
  709. aCircuit.circuitcode.ToString(),
  710. aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
  711. aCircuit.Viewer);
  712. });
  713. MainConsole.Instance.Output(cdt.ToString());
  714. }
  715. private void HandleShowConnections()
  716. {
  717. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  718. cdt.AddColumn("Region", 20);
  719. cdt.AddColumn("Avatar name", 24);
  720. cdt.AddColumn("Circuit code", 12);
  721. cdt.AddColumn("Endpoint", 23);
  722. cdt.AddColumn("Active?", 7);
  723. SceneManager.ForEachScene(
  724. s => s.ForEachClient(
  725. c => cdt.AddRow(
  726. s.Name,
  727. c.Name,
  728. c.CircuitCode.ToString(),
  729. c.RemoteEndPoint.ToString(),
  730. c.IsActive.ToString())));
  731. MainConsole.Instance.Output(cdt.ToString());
  732. }
  733. /// <summary>
  734. /// Use XML2 format to serialize data to a file
  735. /// </summary>
  736. /// <param name="module"></param>
  737. /// <param name="cmdparams"></param>
  738. protected void SavePrimsXml2(string module, string[] cmdparams)
  739. {
  740. if (cmdparams.Length > 5)
  741. {
  742. SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
  743. }
  744. else
  745. {
  746. SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
  747. }
  748. }
  749. /// <summary>
  750. /// Use XML format to serialize data to a file
  751. /// </summary>
  752. /// <param name="module"></param>
  753. /// <param name="cmdparams"></param>
  754. protected void SaveXml(string module, string[] cmdparams)
  755. {
  756. MainConsole.Instance.Output("PLEASE NOTE, save-xml is DEPRECATED and may be REMOVED soon. If you are using this and there is some reason you can't use save-xml2, please file a mantis detailing the reason.");
  757. if (cmdparams.Length > 0)
  758. {
  759. SceneManager.SaveCurrentSceneToXml(cmdparams[2]);
  760. }
  761. else
  762. {
  763. SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
  764. }
  765. }
  766. /// <summary>
  767. /// Loads data and region objects from XML format.
  768. /// </summary>
  769. /// <param name="module"></param>
  770. /// <param name="cmdparams"></param>
  771. protected void LoadXml(string module, string[] cmdparams)
  772. {
  773. MainConsole.Instance.Output("PLEASE NOTE, load-xml is DEPRECATED and may be REMOVED soon. If you are using this and there is some reason you can't use load-xml2, please file a mantis detailing the reason.");
  774. Vector3 loadOffset = new Vector3(0, 0, 0);
  775. if (cmdparams.Length > 2)
  776. {
  777. bool generateNewIDS = false;
  778. if (cmdparams.Length > 3)
  779. {
  780. if (cmdparams[3] == "-newUID")
  781. {
  782. generateNewIDS = true;
  783. }
  784. if (cmdparams.Length > 4)
  785. {
  786. loadOffset.X = (float)Convert.ToDecimal(cmdparams[4], Culture.NumberFormatInfo);
  787. if (cmdparams.Length > 5)
  788. {
  789. loadOffset.Y = (float)Convert.ToDecimal(cmdparams[5], Culture.NumberFormatInfo);
  790. }
  791. if (cmdparams.Length > 6)
  792. {
  793. loadOffset.Z = (float)Convert.ToDecimal(cmdparams[6], Culture.NumberFormatInfo);
  794. }
  795. MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
  796. }
  797. }
  798. SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset);
  799. }
  800. else
  801. {
  802. try
  803. {
  804. SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
  805. }
  806. catch (FileNotFoundException)
  807. {
  808. MainConsole.Instance.Output("Default xml not found. Usage: load-xml <filename>");
  809. }
  810. }
  811. }
  812. /// <summary>
  813. /// Serialize region data to XML2Format
  814. /// </summary>
  815. /// <param name="module"></param>
  816. /// <param name="cmdparams"></param>
  817. protected void SaveXml2(string module, string[] cmdparams)
  818. {
  819. if (cmdparams.Length > 2)
  820. {
  821. SceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
  822. }
  823. else
  824. {
  825. SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
  826. }
  827. }
  828. /// <summary>
  829. /// Load region data from Xml2Format
  830. /// </summary>
  831. /// <param name="module"></param>
  832. /// <param name="cmdparams"></param>
  833. protected void LoadXml2(string module, string[] cmdparams)
  834. {
  835. if (cmdparams.Length > 2)
  836. {
  837. try
  838. {
  839. SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
  840. }
  841. catch (FileNotFoundException)
  842. {
  843. MainConsole.Instance.Output("Specified xml not found. Usage: load xml2 <filename>");
  844. }
  845. }
  846. else
  847. {
  848. try
  849. {
  850. SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
  851. }
  852. catch (FileNotFoundException)
  853. {
  854. MainConsole.Instance.Output("Default xml not found. Usage: load xml2 <filename>");
  855. }
  856. }
  857. }
  858. /// <summary>
  859. /// Load a whole region from an opensimulator archive.
  860. /// </summary>
  861. /// <param name="cmdparams"></param>
  862. protected void LoadOar(string module, string[] cmdparams)
  863. {
  864. try
  865. {
  866. SceneManager.LoadArchiveToCurrentScene(cmdparams);
  867. }
  868. catch (Exception e)
  869. {
  870. MainConsole.Instance.Output(e.Message);
  871. }
  872. }
  873. /// <summary>
  874. /// Save a region to a file, including all the assets needed to restore it.
  875. /// </summary>
  876. /// <param name="cmdparams"></param>
  877. protected void SaveOar(string module, string[] cmdparams)
  878. {
  879. SceneManager.SaveCurrentSceneToArchive(cmdparams);
  880. }
  881. private static string CombineParams(string[] commandParams, int pos)
  882. {
  883. string result = String.Empty;
  884. for (int i = pos; i < commandParams.Length; i++)
  885. {
  886. result += commandParams[i] + " ";
  887. }
  888. result = result.TrimEnd(' ');
  889. return result;
  890. }
  891. #endregion
  892. }
  893. }