opensim-development – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | eva | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ |
||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * * Redistributions of source code must retain the above copyright |
||
8 | * notice, this list of conditions and the following disclaimer. |
||
9 | * * Redistributions in binary form must reproduce the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer in the |
||
11 | * documentation and/or other materials provided with the distribution. |
||
12 | * * Neither the name of the OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections; |
||
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 | } |