opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Diagnostics;
32 using System.IO;
33 using System.Linq;
34 using System.Reflection;
35 using System.Text;
36 using System.Text.RegularExpressions;
37 using System.Timers;
38 using log4net;
39 using NDesk.Options;
40 using Nini.Config;
41 using OpenMetaverse;
42 using OpenSim.Framework;
43 using OpenSim.Framework.Console;
44 using OpenSim.Framework.Servers;
45 using OpenSim.Framework.Monitoring;
46 using OpenSim.Region.Framework.Interfaces;
47 using OpenSim.Region.Framework.Scenes;
48  
49 namespace OpenSim
50 {
51 /// <summary>
52 /// Interactive OpenSim region server
53 /// </summary>
54 public class OpenSim : OpenSimBase
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57  
58 protected string m_startupCommandsFile;
59 protected string m_shutdownCommandsFile;
60 protected bool m_gui = false;
61 protected string m_consoleType = "local";
62 protected uint m_consolePort = 0;
63  
64 /// <summary>
65 /// Prompt to use for simulator command line.
66 /// </summary>
67 private string m_consolePrompt;
68  
69 /// <summary>
70 /// Regex for parsing out special characters in the prompt.
71 /// </summary>
72 private Regex m_consolePromptRegex = new Regex(@"([^\\])\\(\w)", RegexOptions.Compiled);
73  
74 private string m_timedScript = "disabled";
75 private int m_timeInterval = 1200;
76 private Timer m_scriptTimer;
77  
78 public OpenSim(IConfigSource configSource) : base(configSource)
79 {
80 }
81  
82 protected override void ReadExtraConfigSettings()
83 {
84 base.ReadExtraConfigSettings();
85  
86 IConfig startupConfig = Config.Configs["Startup"];
87 IConfig networkConfig = Config.Configs["Network"];
88  
89 int stpMinThreads = 2;
90 int stpMaxThreads = 15;
91  
92 if (startupConfig != null)
93 {
94 m_startupCommandsFile = startupConfig.GetString("startup_console_commands_file", "startup_commands.txt");
95 m_shutdownCommandsFile = startupConfig.GetString("shutdown_console_commands_file", "shutdown_commands.txt");
96  
97 if (startupConfig.GetString("console", String.Empty) == String.Empty)
98 m_gui = startupConfig.GetBoolean("gui", false);
99 else
100 m_consoleType= startupConfig.GetString("console", String.Empty);
101  
102 if (networkConfig != null)
103 m_consolePort = (uint)networkConfig.GetInt("console_port", 0);
104  
105 m_timedScript = startupConfig.GetString("timer_Script", "disabled");
106 if (m_timedScript != "disabled")
107 {
108 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
109 }
110  
111 string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty);
112 FireAndForgetMethod asyncCallMethod;
113 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
114 Util.FireAndForgetMethod = asyncCallMethod;
115  
116 stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15);
117 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15);
118 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
119 }
120  
121 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
122 Util.InitThreadPool(stpMinThreads, stpMaxThreads);
123  
124 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
125 }
126  
127 /// <summary>
128 /// Performs initialisation of the scene, such as loading configuration from disk.
129 /// </summary>
130 protected override void StartupSpecific()
131 {
132 m_log.Info("====================================================================");
133 m_log.Info("========================= STARTING OPENSIM =========================");
134 m_log.Info("====================================================================");
135  
136 //m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString());
137 // http://msdn.microsoft.com/en-us/library/bb384202.aspx
138 //GCSettings.LatencyMode = GCLatencyMode.Batch;
139 //m_log.InfoFormat("[OPENSIM MAIN]: GC Latency Mode: {0}", GCSettings.LatencyMode.ToString());
140  
141 if (m_gui) // Driven by external GUI
142 {
143 m_console = new CommandConsole("Region");
144 }
145 else
146 {
147 switch (m_consoleType)
148 {
149 case "basic":
150 m_console = new CommandConsole("Region");
151 break;
152 case "rest":
153 m_console = new RemoteConsole("Region");
154 ((RemoteConsole)m_console).ReadConfig(Config);
155 break;
156 default:
157 m_console = new LocalConsole("Region");
158 break;
159 }
160 }
161  
162 MainConsole.Instance = m_console;
163  
164 LogEnvironmentInformation();
165 RegisterCommonAppenders(Config.Configs["Startup"]);
166 RegisterConsoleCommands();
167  
168 base.StartupSpecific();
169  
170 MainServer.Instance.AddStreamHandler(new OpenSim.SimStatusHandler());
171 MainServer.Instance.AddStreamHandler(new OpenSim.XSimStatusHandler(this));
172 if (userStatsURI != String.Empty)
173 MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
174  
175 if (managedStatsURI != String.Empty)
176 {
177 string urlBase = String.Format("/{0}/", managedStatsURI);
178 MainServer.Instance.AddHTTPHandler(urlBase, StatsManager.HandleStatsRequest);
179 m_log.InfoFormat("[OPENSIM] Enabling remote managed stats fetch. URL = {0}", urlBase);
180 }
181  
182 if (m_console is RemoteConsole)
183 {
184 if (m_consolePort == 0)
185 {
186 ((RemoteConsole)m_console).SetServer(m_httpServer);
187 }
188 else
189 {
190 ((RemoteConsole)m_console).SetServer(MainServer.GetHttpServer(m_consolePort));
191 }
192 }
193  
194 // Hook up to the watchdog timer
195 Watchdog.OnWatchdogTimeout += WatchdogTimeoutHandler;
196  
197 PrintFileToConsole("startuplogo.txt");
198  
199 // For now, start at the 'root' level by default
200 if (SceneManager.Scenes.Count == 1) // If there is only one region, select it
201 ChangeSelectedRegion("region",
202 new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName});
203 else
204 ChangeSelectedRegion("region", new string[] {"change", "region", "root"});
205  
206 //Run Startup Commands
207 if (String.IsNullOrEmpty(m_startupCommandsFile))
208 {
209 m_log.Info("[STARTUP]: No startup command script specified. Moving on...");
210 }
211 else
212 {
213 RunCommandScript(m_startupCommandsFile);
214 }
215  
216 // Start timer script (run a script every xx seconds)
217 if (m_timedScript != "disabled")
218 {
219 m_scriptTimer = new Timer();
220 m_scriptTimer.Enabled = true;
221 m_scriptTimer.Interval = m_timeInterval*1000;
222 m_scriptTimer.Elapsed += RunAutoTimerScript;
223 }
224 }
225  
226 /// <summary>
227 /// Register standard set of region console commands
228 /// </summary>
229 private void RegisterConsoleCommands()
230 {
231 MainServer.RegisterHttpConsoleCommands(m_console);
232  
233 m_console.Commands.AddCommand("Objects", false, "force update",
234 "force update",
235 "Force the update of all objects on clients",
236 HandleForceUpdate);
237  
238 m_console.Commands.AddCommand("General", false, "change region",
239 "change region <region name>",
240 "Change current console region",
241 ChangeSelectedRegion);
242  
243 m_console.Commands.AddCommand("Archiving", false, "save xml",
244 "save xml",
245 "Save a region's data in XML format",
246 SaveXml);
247  
248 m_console.Commands.AddCommand("Archiving", false, "save xml2",
249 "save xml2",
250 "Save a region's data in XML2 format",
251 SaveXml2);
252  
253 m_console.Commands.AddCommand("Archiving", false, "load xml",
254 "load xml [-newIDs [<x> <y> <z>]]",
255 "Load a region's data from XML format",
256 LoadXml);
257  
258 m_console.Commands.AddCommand("Archiving", false, "load xml2",
259 "load xml2",
260 "Load a region's data from XML2 format",
261 LoadXml2);
262  
263 m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
264 "save prims xml2 [<prim name> <file name>]",
265 "Save named prim to XML2",
266 SavePrimsXml2);
267  
268 m_console.Commands.AddCommand("Archiving", false, "load oar",
269 "load oar [--merge] [--skip-assets]"
270 + " [--force-terrain] [--force-parcels]"
271 + " [--no-objects]"
272 + " [--rotation degrees] [--rotation-center \"<x,y,z>\"]"
273 + " [--displacement \"<x,y,z>\"]"
274 + " [<OAR path>]",
275 "Load a region's data from an OAR archive.",
276 "--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading)." + Environment.NewLine
277 + "--skip-assets will load the OAR but ignore the assets it contains." + Environment.NewLine
278 + "--displacement will add this value to the position of every object loaded" + Environment.NewLine
279 + "--force-terrain forces the loading of terrain from the oar (undoes suppression done by --merge)" + Environment.NewLine
280 + "--force-parcels forces the loading of parcels from the oar (undoes suppression done by --merge)" + Environment.NewLine
281 + "--rotation specified rotation to be applied to the oar. Specified in degrees." + Environment.NewLine
282 + "--rotation-center Location (relative to original OAR) to apply rotation. Default is <128,128,0>" + Environment.NewLine
283 + "--no-objects suppresses the addition of any objects (good for loading only the terrain)" + Environment.NewLine
284 + "The path can be either a filesystem location or a URI."
285 + " If this is not given then the command looks for an OAR named region.oar in the current directory.",
286 LoadOar);
287  
288 m_console.Commands.AddCommand("Archiving", false, "save oar",
289 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
290 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]",
291 "Save a region's data to an OAR archive.",
292 // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
293 "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
294 + "--noassets stops assets being saved to the OAR.\n"
295 + "--publish saves an OAR stripped of owner and last owner information.\n"
296 + " on reload, the estate owner will be the owner of all objects\n"
297 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
298 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
299 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
300 + "--all saves all the regions in the simulator, instead of just the current region.\n"
301 + "The OAR path must be a filesystem path."
302 + " If this is not given then the oar is saved to region.oar in the current directory.",
303 SaveOar);
304  
305 m_console.Commands.AddCommand("Objects", false, "edit scale",
306 "edit scale <name> <x> <y> <z>",
307 "Change the scale of a named prim",
308 HandleEditScale);
309  
310 m_console.Commands.AddCommand("Objects", false, "rotate scene",
311 "rotate scene <degrees> [centerX, centerY]",
312 "Rotates all scene objects around centerX, centerY (defailt 128, 128) (please back up your region before using)",
313 HandleRotateScene);
314  
315 m_console.Commands.AddCommand("Objects", false, "scale scene",
316 "scale scene <factor>",
317 "Scales the scene objects (please back up your region before using)",
318 HandleScaleScene);
319  
320 m_console.Commands.AddCommand("Objects", false, "translate scene",
321 "translate scene xOffset yOffset zOffset",
322 "translates the scene objects (please back up your region before using)",
323 HandleTranslateScene);
324  
325 m_console.Commands.AddCommand("Users", false, "kick user",
326 "kick user <first> <last> [--force] [message]",
327 "Kick a user off the simulator",
328 "The --force option will kick the user without any checks to see whether it's already in the process of closing\n"
329 + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them",
330 KickUserCommand);
331  
332 m_console.Commands.AddCommand("Users", false, "show users",
333 "show users [full]",
334 "Show user data for users currently on the region",
335 "Without the 'full' option, only users actually on the region are shown."
336 + " With the 'full' option child agents of users in neighbouring regions are also shown.",
337 HandleShow);
338  
339 m_console.Commands.AddCommand("Comms", false, "show connections",
340 "show connections",
341 "Show connection data",
342 HandleShow);
343  
344 m_console.Commands.AddCommand("Comms", false, "show circuits",
345 "show circuits",
346 "Show agent circuit data",
347 HandleShow);
348  
349 m_console.Commands.AddCommand("Comms", false, "show pending-objects",
350 "show pending-objects",
351 "Show # of objects on the pending queues of all scene viewers",
352 HandleShow);
353  
354 m_console.Commands.AddCommand("General", false, "show modules",
355 "show modules",
356 "Show module data",
357 HandleShow);
358  
359 m_console.Commands.AddCommand("Regions", false, "show regions",
360 "show regions",
361 "Show region data",
362 HandleShow);
363  
364 m_console.Commands.AddCommand("Regions", false, "show ratings",
365 "show ratings",
366 "Show rating data",
367 HandleShow);
368  
369 m_console.Commands.AddCommand("Objects", false, "backup",
370 "backup",
371 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.",
372 RunCommand);
373  
374 m_console.Commands.AddCommand("Regions", false, "create region",
375 "create region [\"region name\"] <region_file.ini>",
376 "Create a new region.",
377 "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."
378 + " If \"region name\" does not exist in <region_file.ini>, it will be added." + Environment.NewLine
379 + "Without \"region name\", the first region found in <region_file.ini> will be created." + Environment.NewLine
380 + "If <region_file.ini> does not exist, it will be created.",
381 HandleCreateRegion);
382  
383 m_console.Commands.AddCommand("Regions", false, "restart",
384 "restart",
385 "Restart all sims in this instance",
386 RunCommand);
387  
388 m_console.Commands.AddCommand("General", false, "command-script",
389 "command-script <script>",
390 "Run a command script from file",
391 RunCommand);
392  
393 m_console.Commands.AddCommand("Regions", false, "remove-region",
394 "remove-region <name>",
395 "Remove a region from this simulator",
396 RunCommand);
397  
398 m_console.Commands.AddCommand("Regions", false, "delete-region",
399 "delete-region <name>",
400 "Delete a region from disk",
401 RunCommand);
402 }
403  
404 protected override void ShutdownSpecific()
405 {
406 if (m_shutdownCommandsFile != String.Empty)
407 {
408 RunCommandScript(m_shutdownCommandsFile);
409 }
410  
411 base.ShutdownSpecific();
412 }
413  
414 /// <summary>
415 /// Timer to run a specific text file as console commands. Configured in in the main ini file
416 /// </summary>
417 /// <param name="sender"></param>
418 /// <param name="e"></param>
419 private void RunAutoTimerScript(object sender, EventArgs e)
420 {
421 if (m_timedScript != "disabled")
422 {
423 RunCommandScript(m_timedScript);
424 }
425 }
426  
427 private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi)
428 {
429 int now = Environment.TickCount & Int32.MaxValue;
430  
431 m_log.ErrorFormat(
432 "[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}",
433 twi.Thread.Name,
434 twi.Thread.ThreadState,
435 now - twi.LastTick,
436 twi.AlarmMethod != null ? string.Format("Data: {0}", twi.AlarmMethod()) : "");
437 }
438  
439 #region Console Commands
440  
441 /// <summary>
442 /// Kicks users off the region
443 /// </summary>
444 /// <param name="module"></param>
445 /// <param name="cmdparams">name of avatar to kick</param>
446 private void KickUserCommand(string module, string[] cmdparams)
447 {
448 bool force = false;
449  
450 OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; });
451  
452 List<string> mainParams = options.Parse(cmdparams);
453  
454 if (mainParams.Count < 4)
455 return;
456  
457 string alert = null;
458 if (mainParams.Count > 4)
459 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
460  
461 IList agents = SceneManager.GetCurrentSceneAvatars();
462  
463 foreach (ScenePresence presence in agents)
464 {
465 RegionInfo regionInfo = presence.Scene.RegionInfo;
466  
467 if (presence.Firstname.ToLower().Equals(mainParams[2].ToLower()) &&
468 presence.Lastname.ToLower().Equals(mainParams[3].ToLower()))
469 {
470 MainConsole.Instance.Output(
471 String.Format(
472 "Kicking user: {0,-16} {1,-16} {2,-37} in region: {3,-16}",
473 presence.Firstname, presence.Lastname, presence.UUID, regionInfo.RegionName));
474  
475 // kick client...
476 if (alert != null)
477 presence.ControllingClient.Kick(alert);
478 else
479 presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
480  
481 presence.Scene.CloseAgent(presence.UUID, force);
482 break;
483 }
484 }
485  
486 MainConsole.Instance.Output("");
487 }
488  
489 /// <summary>
490 /// Opens a file and uses it as input to the console command parser.
491 /// </summary>
492 /// <param name="fileName">name of file to use as input to the console</param>
493 private static void PrintFileToConsole(string fileName)
494 {
495 if (File.Exists(fileName))
496 {
497 StreamReader readFile = File.OpenText(fileName);
498 string currentLine;
499 while ((currentLine = readFile.ReadLine()) != null)
500 {
501 m_log.Info("[!]" + currentLine);
502 }
503 }
504 }
505  
506 /// <summary>
507 /// Force resending of all updates to all clients in active region(s)
508 /// </summary>
509 /// <param name="module"></param>
510 /// <param name="args"></param>
511 private void HandleForceUpdate(string module, string[] args)
512 {
513 MainConsole.Instance.Output("Updating all clients");
514 SceneManager.ForceCurrentSceneClientUpdate();
515 }
516  
517 /// <summary>
518 /// Edits the scale of a primative with the name specified
519 /// </summary>
520 /// <param name="module"></param>
521 /// <param name="args">0,1, name, x, y, z</param>
522 private void HandleEditScale(string module, string[] args)
523 {
524 if (args.Length == 6)
525 {
526 SceneManager.HandleEditCommandOnCurrentScene(args);
527 }
528 else
529 {
530 MainConsole.Instance.Output("Argument error: edit scale <prim name> <x> <y> <z>");
531 }
532 }
533  
534 private void HandleRotateScene(string module, string[] args)
535 {
536 string usage = "Usage: rotate scene <angle in degrees> [centerX centerY] (centerX and centerY are optional and default to Constants.RegionSize / 2";
537  
538 float centerX = Constants.RegionSize * 0.5f;
539 float centerY = Constants.RegionSize * 0.5f;
540  
541 if (args.Length < 3 || args.Length == 4)
542 {
543 MainConsole.Instance.Output(usage);
544 return;
545 }
546  
547 float angle = (float)(Convert.ToSingle(args[2]) / 180.0 * Math.PI);
548 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, angle);
549  
550 if (args.Length > 4)
551 {
552 centerX = Convert.ToSingle(args[3]);
553 centerY = Convert.ToSingle(args[4]);
554 }
555  
556 Vector3 center = new Vector3(centerX, centerY, 0.0f);
557  
558 SceneManager.ForEachSelectedScene(delegate(Scene scene)
559 {
560 scene.ForEachSOG(delegate(SceneObjectGroup sog)
561 {
562 if (sog.AttachmentPoint == 0)
563 {
564 sog.RootPart.UpdateRotation(rot * sog.GroupRotation);
565 Vector3 offset = sog.AbsolutePosition - center;
566 offset *= rot;
567 sog.UpdateGroupPosition(center + offset);
568 }
569 });
570 });
571 }
572  
573 private void HandleScaleScene(string module, string[] args)
574 {
575 string usage = "Usage: scale scene <factor>";
576  
577 if (args.Length < 3)
578 {
579 MainConsole.Instance.Output(usage);
580 return;
581 }
582  
583 float factor = (float)(Convert.ToSingle(args[2]));
584  
585 float minZ = float.MaxValue;
586  
587 SceneManager.ForEachSelectedScene(delegate(Scene scene)
588 {
589 scene.ForEachSOG(delegate(SceneObjectGroup sog)
590 {
591 if (sog.AttachmentPoint == 0)
592 {
593 if (sog.RootPart.AbsolutePosition.Z < minZ)
594 minZ = sog.RootPart.AbsolutePosition.Z;
595 }
596 });
597 });
598  
599 SceneManager.ForEachSelectedScene(delegate(Scene scene)
600 {
601 scene.ForEachSOG(delegate(SceneObjectGroup sog)
602 {
603 if (sog.AttachmentPoint == 0)
604 {
605 Vector3 tmpRootPos = sog.RootPart.AbsolutePosition;
606 tmpRootPos.Z -= minZ;
607 tmpRootPos *= factor;
608 tmpRootPos.Z += minZ;
609  
610 foreach (SceneObjectPart sop in sog.Parts)
611 {
612 if (sop.ParentID != 0)
613 sop.OffsetPosition *= factor;
614 sop.Scale *= factor;
615 }
616  
617 sog.UpdateGroupPosition(tmpRootPos);
618 }
619 });
620 });
621 }
622  
623 private void HandleTranslateScene(string module, string[] args)
624 {
625 string usage = "Usage: translate scene <xOffset, yOffset, zOffset>";
626  
627 if (args.Length < 5)
628 {
629 MainConsole.Instance.Output(usage);
630 return;
631 }
632  
633 float xOFfset = (float)Convert.ToSingle(args[2]);
634 float yOffset = (float)Convert.ToSingle(args[3]);
635 float zOffset = (float)Convert.ToSingle(args[4]);
636  
637 Vector3 offset = new Vector3(xOFfset, yOffset, zOffset);
638  
639 SceneManager.ForEachSelectedScene(delegate(Scene scene)
640 {
641 scene.ForEachSOG(delegate(SceneObjectGroup sog)
642 {
643 if (sog.AttachmentPoint == 0)
644 sog.UpdateGroupPosition(sog.AbsolutePosition + offset);
645 });
646 });
647 }
648  
649 /// <summary>
650 /// Creates a new region based on the parameters specified. This will ask the user questions on the console
651 /// </summary>
652 /// <param name="module"></param>
653 /// <param name="cmd">0,1,region name, region ini or XML file</param>
654 private void HandleCreateRegion(string module, string[] cmd)
655 {
656 string regionName = string.Empty;
657 string regionFile = string.Empty;
658  
659 if (cmd.Length == 3)
660 {
661 regionFile = cmd[2];
662 }
663 else if (cmd.Length > 3)
664 {
665 regionName = cmd[2];
666 regionFile = cmd[3];
667 }
668  
669 string extension = Path.GetExtension(regionFile).ToLower();
670 bool isXml = extension.Equals(".xml");
671 bool isIni = extension.Equals(".ini");
672  
673 if (!isXml && !isIni)
674 {
675 MainConsole.Instance.Output("Usage: create region [\"region name\"] <region_file.ini>");
676 return;
677 }
678  
679 if (!Path.IsPathRooted(regionFile))
680 {
681 string regionsDir = ConfigSource.Source.Configs["Startup"].GetString("regionload_regionsdir", "Regions").Trim();
682 regionFile = Path.Combine(regionsDir, regionFile);
683 }
684  
685 RegionInfo regInfo;
686 if (isXml)
687 {
688 regInfo = new RegionInfo(regionName, regionFile, false, ConfigSource.Source);
689 }
690 else
691 {
692 regInfo = new RegionInfo(regionName, regionFile, false, ConfigSource.Source, regionName);
693 }
694  
695 Scene existingScene;
696 if (SceneManager.TryGetScene(regInfo.RegionID, out existingScene))
697 {
698 MainConsole.Instance.OutputFormat(
699 "ERROR: Cannot create region {0} with ID {1}, this ID is already assigned to region {2}",
700 regInfo.RegionName, regInfo.RegionID, existingScene.RegionInfo.RegionName);
701  
702 return;
703 }
704  
705 bool changed = PopulateRegionEstateInfo(regInfo);
706 IScene scene;
707 CreateRegion(regInfo, true, out scene);
708  
709 if (changed)
710 regInfo.EstateSettings.Save();
711 }
712  
713 /// <summary>
714 /// Runs commands issued by the server console from the operator
715 /// </summary>
716 /// <param name="command">The first argument of the parameter (the command)</param>
717 /// <param name="cmdparams">Additional arguments passed to the command</param>
718 public void RunCommand(string module, string[] cmdparams)
719 {
720 List<string> args = new List<string>(cmdparams);
721 if (args.Count < 1)
722 return;
723  
724 string command = args[0];
725 args.RemoveAt(0);
726  
727 cmdparams = args.ToArray();
728  
729 switch (command)
730 {
731 case "backup":
732 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
733 SceneManager.BackupCurrentScene();
734 break;
735  
736 case "remove-region":
737 string regRemoveName = CombineParams(cmdparams, 0);
738  
739 Scene removeScene;
740 if (SceneManager.TryGetScene(regRemoveName, out removeScene))
741 RemoveRegion(removeScene, false);
742 else
743 MainConsole.Instance.Output("No region with that name");
744 break;
745  
746 case "delete-region":
747 string regDeleteName = CombineParams(cmdparams, 0);
748  
749 Scene killScene;
750 if (SceneManager.TryGetScene(regDeleteName, out killScene))
751 RemoveRegion(killScene, true);
752 else
753 MainConsole.Instance.Output("no region with that name");
754 break;
755  
756 case "restart":
757 SceneManager.RestartCurrentScene();
758 break;
759 }
760 }
761  
762 /// <summary>
763 /// Change the currently selected region. The selected region is that operated upon by single region commands.
764 /// </summary>
765 /// <param name="cmdParams"></param>
766 protected void ChangeSelectedRegion(string module, string[] cmdparams)
767 {
768 if (cmdparams.Length > 2)
769 {
770 string newRegionName = CombineParams(cmdparams, 2);
771  
772 if (!SceneManager.TrySetCurrentScene(newRegionName))
773 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
774 else
775 RefreshPrompt();
776 }
777 else
778 {
779 MainConsole.Instance.Output("Usage: change region <region name>");
780 }
781 }
782  
783 /// <summary>
784 /// Refreshs prompt with the current selection details.
785 /// </summary>
786 private void RefreshPrompt()
787 {
788 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
789 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
790  
791 // m_log.DebugFormat("Original prompt is {0}", m_consolePrompt);
792 string prompt = m_consolePrompt;
793  
794 // Replace "\R" with the region name
795 // Replace "\\" with "\"
796 prompt = m_consolePromptRegex.Replace(prompt, m =>
797 {
798 // m_log.DebugFormat("Matched {0}", m.Groups[2].Value);
799 if (m.Groups[2].Value == "R")
800 return m.Groups[1].Value + regionName;
801 else
802 return m.Groups[0].Value;
803 });
804  
805 m_console.DefaultPrompt = prompt;
806 m_console.ConsoleScene = SceneManager.CurrentScene;
807 }
808  
809 protected override void HandleRestartRegion(RegionInfo whichRegion)
810 {
811 base.HandleRestartRegion(whichRegion);
812  
813 // Where we are restarting multiple scenes at once, a previous call to RefreshPrompt may have set the
814 // m_console.ConsoleScene to null (indicating all scenes).
815 if (m_console.ConsoleScene != null && whichRegion.RegionName == ((Scene)m_console.ConsoleScene).Name)
816 SceneManager.TrySetCurrentScene(whichRegion.RegionName);
817  
818 RefreshPrompt();
819 }
820  
821 // see BaseOpenSimServer
822 /// <summary>
823 /// Many commands list objects for debugging. Some of the types are listed here
824 /// </summary>
825 /// <param name="mod"></param>
826 /// <param name="cmd"></param>
827 public override void HandleShow(string mod, string[] cmd)
828 {
829 base.HandleShow(mod, cmd);
830  
831 List<string> args = new List<string>(cmd);
832 args.RemoveAt(0);
833 string[] showParams = args.ToArray();
834  
835 switch (showParams[0])
836 {
837 case "users":
838 IList agents;
839 if (showParams.Length > 1 && showParams[1] == "full")
840 {
841 agents = SceneManager.GetCurrentScenePresences();
842 } else
843 {
844 agents = SceneManager.GetCurrentSceneAvatars();
845 }
846  
847 MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count));
848  
849 MainConsole.Instance.Output(
850 String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname",
851 "Agent ID", "Root/Child", "Region", "Position")
852 );
853  
854 foreach (ScenePresence presence in agents)
855 {
856 RegionInfo regionInfo = presence.Scene.RegionInfo;
857 string regionName;
858  
859 if (regionInfo == null)
860 {
861 regionName = "Unresolvable";
862 } else
863 {
864 regionName = regionInfo.RegionName;
865 }
866  
867 MainConsole.Instance.Output(
868 String.Format(
869 "{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}",
870 presence.Firstname,
871 presence.Lastname,
872 presence.UUID,
873 presence.IsChildAgent ? "Child" : "Root",
874 regionName,
875 presence.AbsolutePosition.ToString())
876 );
877 }
878  
879 MainConsole.Instance.Output(String.Empty);
880 break;
881  
882 case "connections":
883 HandleShowConnections();
884 break;
885  
886 case "circuits":
887 HandleShowCircuits();
888 break;
889  
890 case "modules":
891 SceneManager.ForEachSelectedScene(
892 scene =>
893 {
894 MainConsole.Instance.OutputFormat("Loaded region modules in {0} are:", scene.Name);
895  
896 List<IRegionModuleBase> sharedModules = new List<IRegionModuleBase>();
897 List<IRegionModuleBase> nonSharedModules = new List<IRegionModuleBase>();
898  
899 foreach (IRegionModuleBase module in scene.RegionModules.Values)
900 {
901 if (module.GetType().GetInterface("ISharedRegionModule") != null)
902 nonSharedModules.Add(module);
903 else
904 sharedModules.Add(module);
905 }
906  
907 foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name))
908 MainConsole.Instance.OutputFormat("New Region Module (Shared): {0}", module.Name);
909  
910 foreach (IRegionModuleBase module in nonSharedModules.OrderBy(m => m.Name))
911 MainConsole.Instance.OutputFormat("New Region Module (Non-Shared): {0}", module.Name);
912 }
913 );
914  
915 MainConsole.Instance.Output("");
916 break;
917  
918 case "regions":
919 SceneManager.ForEachScene(
920 delegate(Scene scene)
921 {
922 MainConsole.Instance.Output(String.Format(
923 "Region Name: {0}, Region XLoc: {1}, Region YLoc: {2}, Region Port: {3}, Estate Name: {4}",
924 scene.RegionInfo.RegionName,
925 scene.RegionInfo.RegionLocX,
926 scene.RegionInfo.RegionLocY,
927 scene.RegionInfo.InternalEndPoint.Port,
928 scene.RegionInfo.EstateSettings.EstateName));
929 });
930 break;
931  
932 case "ratings":
933 SceneManager.ForEachScene(
934 delegate(Scene scene)
935 {
936 string rating = "";
937 if (scene.RegionInfo.RegionSettings.Maturity == 1)
938 {
939 rating = "MATURE";
940 }
941 else if (scene.RegionInfo.RegionSettings.Maturity == 2)
942 {
943 rating = "ADULT";
944 }
945 else
946 {
947 rating = "PG";
948 }
949 MainConsole.Instance.Output(String.Format(
950 "Region Name: {0}, Region Rating {1}",
951 scene.RegionInfo.RegionName,
952 rating));
953 });
954 break;
955 }
956 }
957  
958 private void HandleShowCircuits()
959 {
960 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
961 cdt.AddColumn("Region", 20);
962 cdt.AddColumn("Avatar name", 24);
963 cdt.AddColumn("Type", 5);
964 cdt.AddColumn("Code", 10);
965 cdt.AddColumn("IP", 16);
966 cdt.AddColumn("Viewer Name", 24);
967  
968 SceneManager.ForEachScene(
969 s =>
970 {
971 foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
972 cdt.AddRow(
973 s.Name,
974 aCircuit.Name,
975 aCircuit.child ? "child" : "root",
976 aCircuit.circuitcode.ToString(),
977 aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
978 aCircuit.Viewer);
979 });
980  
981 MainConsole.Instance.Output(cdt.ToString());
982 }
983  
984 private void HandleShowConnections()
985 {
986 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
987 cdt.AddColumn("Region", 20);
988 cdt.AddColumn("Avatar name", 24);
989 cdt.AddColumn("Circuit code", 12);
990 cdt.AddColumn("Endpoint", 23);
991 cdt.AddColumn("Active?", 7);
992  
993 SceneManager.ForEachScene(
994 s => s.ForEachClient(
995 c => cdt.AddRow(
996 s.Name,
997 c.Name,
998 c.CircuitCode.ToString(),
999 c.RemoteEndPoint.ToString(),
1000 c.IsActive.ToString())));
1001  
1002 MainConsole.Instance.Output(cdt.ToString());
1003 }
1004  
1005 /// <summary>
1006 /// Use XML2 format to serialize data to a file
1007 /// </summary>
1008 /// <param name="module"></param>
1009 /// <param name="cmdparams"></param>
1010 protected void SavePrimsXml2(string module, string[] cmdparams)
1011 {
1012 if (cmdparams.Length > 5)
1013 {
1014 SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
1015 }
1016 else
1017 {
1018 SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
1019 }
1020 }
1021  
1022 /// <summary>
1023 /// Use XML format to serialize data to a file
1024 /// </summary>
1025 /// <param name="module"></param>
1026 /// <param name="cmdparams"></param>
1027 protected void SaveXml(string module, string[] cmdparams)
1028 {
1029 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.");
1030  
1031 if (cmdparams.Length > 0)
1032 {
1033 SceneManager.SaveCurrentSceneToXml(cmdparams[2]);
1034 }
1035 else
1036 {
1037 SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
1038 }
1039 }
1040  
1041 /// <summary>
1042 /// Loads data and region objects from XML format.
1043 /// </summary>
1044 /// <param name="module"></param>
1045 /// <param name="cmdparams"></param>
1046 protected void LoadXml(string module, string[] cmdparams)
1047 {
1048 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.");
1049  
1050 Vector3 loadOffset = new Vector3(0, 0, 0);
1051 if (cmdparams.Length > 2)
1052 {
1053 bool generateNewIDS = false;
1054 if (cmdparams.Length > 3)
1055 {
1056 if (cmdparams[3] == "-newUID")
1057 {
1058 generateNewIDS = true;
1059 }
1060 if (cmdparams.Length > 4)
1061 {
1062 loadOffset.X = (float)Convert.ToDecimal(cmdparams[4], Culture.NumberFormatInfo);
1063 if (cmdparams.Length > 5)
1064 {
1065 loadOffset.Y = (float)Convert.ToDecimal(cmdparams[5], Culture.NumberFormatInfo);
1066 }
1067 if (cmdparams.Length > 6)
1068 {
1069 loadOffset.Z = (float)Convert.ToDecimal(cmdparams[6], Culture.NumberFormatInfo);
1070 }
1071 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
1072 }
1073 }
1074 SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset);
1075 }
1076 else
1077 {
1078 try
1079 {
1080 SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
1081 }
1082 catch (FileNotFoundException)
1083 {
1084 MainConsole.Instance.Output("Default xml not found. Usage: load-xml <filename>");
1085 }
1086 }
1087 }
1088 /// <summary>
1089 /// Serialize region data to XML2Format
1090 /// </summary>
1091 /// <param name="module"></param>
1092 /// <param name="cmdparams"></param>
1093 protected void SaveXml2(string module, string[] cmdparams)
1094 {
1095 if (cmdparams.Length > 2)
1096 {
1097 SceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
1098 }
1099 else
1100 {
1101 SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
1102 }
1103 }
1104  
1105 /// <summary>
1106 /// Load region data from Xml2Format
1107 /// </summary>
1108 /// <param name="module"></param>
1109 /// <param name="cmdparams"></param>
1110 protected void LoadXml2(string module, string[] cmdparams)
1111 {
1112 if (cmdparams.Length > 2)
1113 {
1114 try
1115 {
1116 SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
1117 }
1118 catch (FileNotFoundException)
1119 {
1120 MainConsole.Instance.Output("Specified xml not found. Usage: load xml2 <filename>");
1121 }
1122 }
1123 else
1124 {
1125 try
1126 {
1127 SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
1128 }
1129 catch (FileNotFoundException)
1130 {
1131 MainConsole.Instance.Output("Default xml not found. Usage: load xml2 <filename>");
1132 }
1133 }
1134 }
1135  
1136 /// <summary>
1137 /// Load a whole region from an opensimulator archive.
1138 /// </summary>
1139 /// <param name="cmdparams"></param>
1140 protected void LoadOar(string module, string[] cmdparams)
1141 {
1142 try
1143 {
1144 SceneManager.LoadArchiveToCurrentScene(cmdparams);
1145 }
1146 catch (Exception e)
1147 {
1148 MainConsole.Instance.Output(e.Message);
1149 }
1150 }
1151  
1152 /// <summary>
1153 /// Save a region to a file, including all the assets needed to restore it.
1154 /// </summary>
1155 /// <param name="cmdparams"></param>
1156 protected void SaveOar(string module, string[] cmdparams)
1157 {
1158 SceneManager.SaveCurrentSceneToArchive(cmdparams);
1159 }
1160  
1161 private static string CombineParams(string[] commandParams, int pos)
1162 {
1163 string result = String.Empty;
1164 for (int i = pos; i < commandParams.Length; i++)
1165 {
1166 result += commandParams[i] + " ";
1167 }
1168 result = result.TrimEnd(' ');
1169 return result;
1170 }
1171  
1172 #endregion
1173 }
1174 }