opensim – 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.Generic;
30 using System.Net;
31 using System.Reflection;
32 using Nini.Config;
33 using log4net;
34 using OpenSim.Framework;
35 using OpenSim.Framework.Console;
36 using OpenSim.Data;
37 using OpenSim.Server.Base;
38 using OpenSim.Services.Interfaces;
39 using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40 using OpenMetaverse;
41  
42 namespace OpenSim.Services.GridService
43 {
44 public class GridService : GridServiceBase, IGridService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49  
50 private bool m_DeleteOnUnregister = true;
51 private static GridService m_RootInstance = null;
52 protected IConfigSource m_config;
53 protected static HypergridLinker m_HypergridLinker;
54  
55 protected IAuthenticationService m_AuthenticationService = null;
56 protected bool m_AllowDuplicateNames = false;
57 protected bool m_AllowHypergridMapSearch = false;
58  
59 public GridService(IConfigSource config)
60 : base(config)
61 {
62 m_log.DebugFormat("[GRID SERVICE]: Starting...");
63  
64 m_config = config;
65 IConfig gridConfig = config.Configs["GridService"];
66 if (gridConfig != null)
67 {
68 m_DeleteOnUnregister = gridConfig.GetBoolean("DeleteOnUnregister", true);
69  
70 string authService = gridConfig.GetString("AuthenticationService", String.Empty);
71  
72 if (authService != String.Empty)
73 {
74 Object[] args = new Object[] { config };
75 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args);
76 }
77 m_AllowDuplicateNames = gridConfig.GetBoolean("AllowDuplicateNames", m_AllowDuplicateNames);
78 m_AllowHypergridMapSearch = gridConfig.GetBoolean("AllowHypergridMapSearch", m_AllowHypergridMapSearch);
79 }
80  
81 if (m_RootInstance == null)
82 {
83 m_RootInstance = this;
84  
85 if (MainConsole.Instance != null)
86 {
87 MainConsole.Instance.Commands.AddCommand("Regions", true,
88 "deregister region id",
89 "deregister region id <region-id>+",
90 "Deregister a region manually.",
91 String.Empty,
92 HandleDeregisterRegion);
93  
94 // A messy way of stopping this command being added if we are in standalone (since the simulator
95 // has an identically named command
96 //
97 // XXX: We're relying on the OpenSimulator version being registered first, which is not well defined.
98 if (MainConsole.Instance.Commands.Resolve(new string[] { "show", "regions" }).Length == 0)
99 MainConsole.Instance.Commands.AddCommand("Regions", true,
100 "show regions",
101 "show regions",
102 "Show details on all regions",
103 String.Empty,
104 HandleShowRegions);
105  
106 MainConsole.Instance.Commands.AddCommand("Regions", true,
107 "show region name",
108 "show region name <Region name>",
109 "Show details on a region",
110 String.Empty,
111 HandleShowRegion);
112  
113 MainConsole.Instance.Commands.AddCommand("Regions", true,
114 "show region at",
115 "show region at <x-coord> <y-coord>",
116 "Show details on a region at the given co-ordinate.",
117 "For example, show region at 1000 1000",
118 HandleShowRegionAt);
119  
120 MainConsole.Instance.Commands.AddCommand("Regions", true,
121 "set region flags",
122 "set region flags <Region name> <flags>",
123 "Set database flags for region",
124 String.Empty,
125 HandleSetFlags);
126 }
127 m_HypergridLinker = new HypergridLinker(m_config, this, m_Database);
128 }
129 }
130  
131 #region IGridService
132  
133 public string RegisterRegion(UUID scopeID, GridRegion regionInfos)
134 {
135 IConfig gridConfig = m_config.Configs["GridService"];
136  
137 if (regionInfos.RegionID == UUID.Zero)
138 return "Invalid RegionID - cannot be zero UUID";
139  
140 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
141 if ((region != null) && (region.RegionID != regionInfos.RegionID))
142 {
143 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
144 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
145 return "Region overlaps another region";
146 }
147  
148 if (region != null)
149 {
150 // There is a preexisting record
151 //
152 // Get it's flags
153 //
154 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(region.Data["flags"]);
155  
156 // Is this a reservation?
157 //
158 if ((rflags & OpenSim.Framework.RegionFlags.Reservation) != 0)
159 {
160 // Regions reserved for the null key cannot be taken.
161 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString())
162 return "Region location is reserved";
163  
164 // Treat it as an auth request
165 //
166 // NOTE: Fudging the flags value here, so these flags
167 // should not be used elsewhere. Don't optimize
168 // this with the later retrieval of the same flags!
169 rflags |= OpenSim.Framework.RegionFlags.Authenticate;
170 }
171  
172 if ((rflags & OpenSim.Framework.RegionFlags.Authenticate) != 0)
173 {
174 // Can we authenticate at all?
175 //
176 if (m_AuthenticationService == null)
177 return "No authentication possible";
178  
179 if (!m_AuthenticationService.Verify(new UUID(region.Data["PrincipalID"].ToString()), regionInfos.Token, 30))
180 return "Bad authentication";
181 }
182 }
183  
184 // If we get here, the destination is clear. Now for the real check.
185  
186 if (!m_AllowDuplicateNames)
187 {
188 List<RegionData> dupe = m_Database.Get(Util.EscapeForLike(regionInfos.RegionName), scopeID);
189 if (dupe != null && dupe.Count > 0)
190 {
191 foreach (RegionData d in dupe)
192 {
193 if (d.RegionID != regionInfos.RegionID)
194 {
195 m_log.WarnFormat("[GRID SERVICE]: Region tried to register using a duplicate name. New region: {0} ({1}), existing region: {2} ({3}).",
196 regionInfos.RegionName, regionInfos.RegionID, d.RegionName, d.RegionID);
197 return "Duplicate region name";
198 }
199 }
200 }
201 }
202  
203 // If there is an old record for us, delete it if it is elsewhere.
204 region = m_Database.Get(regionInfos.RegionID, scopeID);
205 if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
206 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
207 {
208 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.NoMove) != 0)
209 return "Can't move this region";
210  
211 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.LockedOut) != 0)
212 return "Region locked out";
213  
214 // Region reregistering in other coordinates. Delete the old entry
215 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
216 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
217  
218 try
219 {
220 m_Database.Delete(regionInfos.RegionID);
221 }
222 catch (Exception e)
223 {
224 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
225 }
226 }
227  
228 // Everything is ok, let's register
229 RegionData rdata = RegionInfo2RegionData(regionInfos);
230 rdata.ScopeID = scopeID;
231  
232 if (region != null)
233 {
234 int oldFlags = Convert.ToInt32(region.Data["flags"]);
235  
236 oldFlags &= ~(int)OpenSim.Framework.RegionFlags.Reservation;
237  
238 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags
239 }
240 else
241 {
242 rdata.Data["flags"] = "0";
243 if ((gridConfig != null) && rdata.RegionName != string.Empty)
244 {
245 int newFlags = 0;
246 string regionName = rdata.RegionName.Trim().Replace(' ', '_');
247 newFlags = ParseFlags(newFlags, gridConfig.GetString("DefaultRegionFlags", String.Empty));
248 newFlags = ParseFlags(newFlags, gridConfig.GetString("Region_" + regionName, String.Empty));
249 newFlags = ParseFlags(newFlags, gridConfig.GetString("Region_" + rdata.RegionID.ToString(), String.Empty));
250 rdata.Data["flags"] = newFlags.ToString();
251 }
252 }
253  
254 int flags = Convert.ToInt32(rdata.Data["flags"]);
255 flags |= (int)OpenSim.Framework.RegionFlags.RegionOnline;
256 rdata.Data["flags"] = flags.ToString();
257  
258 try
259 {
260 rdata.Data["last_seen"] = Util.UnixTimeSinceEpoch();
261 m_Database.Store(rdata);
262 }
263 catch (Exception e)
264 {
265 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
266 }
267  
268 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3} with flags {4}",
269 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY,
270 (OpenSim.Framework.RegionFlags)flags);
271  
272 return String.Empty;
273 }
274  
275 public bool DeregisterRegion(UUID regionID)
276 {
277 RegionData region = m_Database.Get(regionID, UUID.Zero);
278 if (region == null)
279 return false;
280  
281 m_log.DebugFormat(
282 "[GRID SERVICE]: Deregistering region {0} ({1}) at {2}-{3}",
283 region.RegionName, region.RegionID, region.coordX, region.coordY);
284  
285 int flags = Convert.ToInt32(region.Data["flags"]);
286  
287 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0)
288 {
289 flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline;
290 region.Data["flags"] = flags.ToString();
291 region.Data["last_seen"] = Util.UnixTimeSinceEpoch();
292 try
293 {
294 m_Database.Store(region);
295 }
296 catch (Exception e)
297 {
298 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
299 }
300  
301 return true;
302  
303 }
304  
305 return m_Database.Delete(regionID);
306 }
307  
308 public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
309 {
310 List<GridRegion> rinfos = new List<GridRegion>();
311 RegionData region = m_Database.Get(regionID, scopeID);
312  
313 if (region != null)
314 {
315 // Not really? Maybe?
316 // The adjacent regions are presumed to be the same size as the current region
317 List<RegionData> rdatas = m_Database.Get(
318 region.posX - region.sizeX - 1, region.posY - region.sizeY - 1,
319 region.posX + region.sizeX + 1, region.posY + region.sizeY + 1, scopeID);
320  
321 foreach (RegionData rdata in rdatas)
322 {
323 if (rdata.RegionID != regionID)
324 {
325 int flags = Convert.ToInt32(rdata.Data["flags"]);
326 if ((flags & (int)Framework.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours
327 rinfos.Add(RegionData2RegionInfo(rdata));
328 }
329 }
330  
331 // m_log.DebugFormat("[GRID SERVICE]: region {0} has {1} neighbours", region.RegionName, rinfos.Count);
332 }
333 else
334 {
335 m_log.WarnFormat(
336 "[GRID SERVICE]: GetNeighbours() called for scope {0}, region {1} but no such region found",
337 scopeID, regionID);
338 }
339  
340 return rinfos;
341 }
342  
343 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
344 {
345 RegionData rdata = m_Database.Get(regionID, scopeID);
346 if (rdata != null)
347 return RegionData2RegionInfo(rdata);
348  
349 return null;
350 }
351  
352 // Get a region given its base coordinates.
353 // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
354 // be the base coordinate of the region.
355 // The snapping is technically unnecessary but is harmless because regions are always
356 // multiples of the legacy region size (256).
357 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
358 {
359 int snapX = (int)(x / Constants.RegionSize) * (int)Constants.RegionSize;
360 int snapY = (int)(y / Constants.RegionSize) * (int)Constants.RegionSize;
361 RegionData rdata = m_Database.Get(snapX, snapY, scopeID);
362 if (rdata != null)
363 return RegionData2RegionInfo(rdata);
364  
365 return null;
366 }
367  
368 public GridRegion GetRegionByName(UUID scopeID, string name)
369 {
370 List<RegionData> rdatas = m_Database.Get(Util.EscapeForLike(name), scopeID);
371 if ((rdatas != null) && (rdatas.Count > 0))
372 return RegionData2RegionInfo(rdatas[0]); // get the first
373  
374 if (m_AllowHypergridMapSearch)
375 {
376 GridRegion r = GetHypergridRegionByName(scopeID, name);
377 if (r != null)
378 return r;
379 }
380  
381 return null;
382 }
383  
384 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
385 {
386 // m_log.DebugFormat("[GRID SERVICE]: GetRegionsByName {0}", name);
387  
388 List<RegionData> rdatas = m_Database.Get(Util.EscapeForLike(name) + "%", scopeID);
389  
390 int count = 0;
391 List<GridRegion> rinfos = new List<GridRegion>();
392  
393 if (rdatas != null)
394 {
395 // m_log.DebugFormat("[GRID SERVICE]: Found {0} regions", rdatas.Count);
396 foreach (RegionData rdata in rdatas)
397 {
398 if (count++ < maxNumber)
399 rinfos.Add(RegionData2RegionInfo(rdata));
400 }
401 }
402  
403 if (m_AllowHypergridMapSearch && (rdatas == null || (rdatas != null && rdatas.Count == 0)))
404 {
405 GridRegion r = GetHypergridRegionByName(scopeID, name);
406 if (r != null)
407 rinfos.Add(r);
408 }
409  
410 return rinfos;
411 }
412  
413 /// <summary>
414 /// Get a hypergrid region.
415 /// </summary>
416 /// <param name="scopeID"></param>
417 /// <param name="name"></param>
418 /// <returns>null if no hypergrid region could be found.</returns>
419 protected GridRegion GetHypergridRegionByName(UUID scopeID, string name)
420 {
421 if (name.Contains("."))
422 return m_HypergridLinker.LinkRegion(scopeID, name);
423 else
424 return null;
425 }
426  
427 public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
428 {
429 int xminSnap = (int)(xmin / Constants.RegionSize) * (int)Constants.RegionSize;
430 int xmaxSnap = (int)(xmax / Constants.RegionSize) * (int)Constants.RegionSize;
431 int yminSnap = (int)(ymin / Constants.RegionSize) * (int)Constants.RegionSize;
432 int ymaxSnap = (int)(ymax / Constants.RegionSize) * (int)Constants.RegionSize;
433  
434 List<RegionData> rdatas = m_Database.Get(xminSnap, yminSnap, xmaxSnap, ymaxSnap, scopeID);
435 List<GridRegion> rinfos = new List<GridRegion>();
436 foreach (RegionData rdata in rdatas)
437 rinfos.Add(RegionData2RegionInfo(rdata));
438  
439 return rinfos;
440 }
441  
442 #endregion
443  
444 #region Data structure conversions
445  
446 public RegionData RegionInfo2RegionData(GridRegion rinfo)
447 {
448 RegionData rdata = new RegionData();
449 rdata.posX = (int)rinfo.RegionLocX;
450 rdata.posY = (int)rinfo.RegionLocY;
451 rdata.sizeX = rinfo.RegionSizeX;
452 rdata.sizeY = rinfo.RegionSizeY;
453 rdata.RegionID = rinfo.RegionID;
454 rdata.RegionName = rinfo.RegionName;
455 rdata.Data = rinfo.ToKeyValuePairs();
456 rdata.Data["regionHandle"] = Utils.UIntsToLong((uint)rdata.posX, (uint)rdata.posY);
457 rdata.Data["owner_uuid"] = rinfo.EstateOwner.ToString();
458 return rdata;
459 }
460  
461 public GridRegion RegionData2RegionInfo(RegionData rdata)
462 {
463 GridRegion rinfo = new GridRegion(rdata.Data);
464 rinfo.RegionLocX = rdata.posX;
465 rinfo.RegionLocY = rdata.posY;
466 rinfo.RegionSizeX = rdata.sizeX;
467 rinfo.RegionSizeY = rdata.sizeY;
468 rinfo.RegionID = rdata.RegionID;
469 rinfo.RegionName = rdata.RegionName;
470 rinfo.ScopeID = rdata.ScopeID;
471  
472 return rinfo;
473 }
474  
475 #endregion
476  
477 public List<GridRegion> GetDefaultRegions(UUID scopeID)
478 {
479 List<GridRegion> ret = new List<GridRegion>();
480  
481 List<RegionData> regions = m_Database.GetDefaultRegions(scopeID);
482  
483 foreach (RegionData r in regions)
484 {
485 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
486 ret.Add(RegionData2RegionInfo(r));
487 }
488  
489 m_log.DebugFormat("[GRID SERVICE]: GetDefaultRegions returning {0} regions", ret.Count);
490 return ret;
491 }
492  
493 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
494 {
495 List<GridRegion> ret = new List<GridRegion>();
496  
497 List<RegionData> regions = m_Database.GetDefaultHypergridRegions(scopeID);
498  
499 foreach (RegionData r in regions)
500 {
501 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
502 ret.Add(RegionData2RegionInfo(r));
503 }
504  
505 int hgDefaultRegionsFoundOnline = regions.Count;
506  
507 // For now, hypergrid default regions will always be given precedence but we will also return simple default
508 // regions in case no specific hypergrid regions are specified.
509 ret.AddRange(GetDefaultRegions(scopeID));
510  
511 int normalDefaultRegionsFoundOnline = ret.Count - hgDefaultRegionsFoundOnline;
512  
513 m_log.DebugFormat(
514 "[GRID SERVICE]: GetDefaultHypergridRegions returning {0} hypergrid default and {1} normal default regions",
515 hgDefaultRegionsFoundOnline, normalDefaultRegionsFoundOnline);
516  
517 return ret;
518 }
519  
520 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
521 {
522 List<GridRegion> ret = new List<GridRegion>();
523  
524 List<RegionData> regions = m_Database.GetFallbackRegions(scopeID, x, y);
525  
526 foreach (RegionData r in regions)
527 {
528 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
529 ret.Add(RegionData2RegionInfo(r));
530 }
531  
532 m_log.DebugFormat("[GRID SERVICE]: Fallback returned {0} regions", ret.Count);
533 return ret;
534 }
535  
536 public List<GridRegion> GetHyperlinks(UUID scopeID)
537 {
538 List<GridRegion> ret = new List<GridRegion>();
539  
540 List<RegionData> regions = m_Database.GetHyperlinks(scopeID);
541  
542 foreach (RegionData r in regions)
543 {
544 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
545 ret.Add(RegionData2RegionInfo(r));
546 }
547  
548 m_log.DebugFormat("[GRID SERVICE]: Hyperlinks returned {0} regions", ret.Count);
549 return ret;
550 }
551  
552 public int GetRegionFlags(UUID scopeID, UUID regionID)
553 {
554 RegionData region = m_Database.Get(regionID, scopeID);
555  
556 if (region != null)
557 {
558 int flags = Convert.ToInt32(region.Data["flags"]);
559 //m_log.DebugFormat("[GRID SERVICE]: Request for flags of {0}: {1}", regionID, flags);
560 return flags;
561 }
562 else
563 return -1;
564 }
565  
566 private void HandleDeregisterRegion(string module, string[] cmd)
567 {
568 if (cmd.Length < 4)
569 {
570 MainConsole.Instance.Output("Usage: degregister region id <region-id>+");
571 return;
572 }
573  
574 for (int i = 3; i < cmd.Length; i++)
575 {
576 string rawRegionUuid = cmd[i];
577 UUID regionUuid;
578  
579 if (!UUID.TryParse(rawRegionUuid, out regionUuid))
580 {
581 MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid);
582 return;
583 }
584  
585 GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid);
586  
587 if (region == null)
588 {
589 MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
590 return;
591 }
592  
593 if (DeregisterRegion(regionUuid))
594 {
595 MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid);
596 }
597 else
598 {
599 // I don't think this can ever occur if we know that the region exists.
600 MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
601 }
602 }
603 }
604  
605 private void HandleShowRegions(string module, string[] cmd)
606 {
607 if (cmd.Length != 2)
608 {
609 MainConsole.Instance.Output("Syntax: show regions");
610 return;
611 }
612  
613 List<RegionData> regions = m_Database.Get(int.MinValue, int.MinValue, int.MaxValue, int.MaxValue, UUID.Zero);
614  
615 OutputRegionsToConsoleSummary(regions);
616 }
617  
618  
619 private void HandleShowRegion(string module, string[] cmd)
620 {
621 if (cmd.Length != 4)
622 {
623 MainConsole.Instance.Output("Syntax: show region name <region name>");
624 return;
625 }
626  
627 string regionName = cmd[3];
628  
629 List<RegionData> regions = m_Database.Get(Util.EscapeForLike(regionName), UUID.Zero);
630 if (regions == null || regions.Count < 1)
631 {
632 MainConsole.Instance.Output("No region with name {0} found", regionName);
633 return;
634 }
635  
636 OutputRegionsToConsole(regions);
637 }
638  
639 private void HandleShowRegionAt(string module, string[] cmd)
640 {
641 if (cmd.Length != 5)
642 {
643 MainConsole.Instance.Output("Syntax: show region at <x-coord> <y-coord>");
644 return;
645 }
646  
647 uint x, y;
648 if (!uint.TryParse(cmd[3], out x))
649 {
650 MainConsole.Instance.Output("x-coord must be an integer");
651 return;
652 }
653  
654 if (!uint.TryParse(cmd[4], out y))
655 {
656 MainConsole.Instance.Output("y-coord must be an integer");
657 return;
658 }
659  
660 RegionData region = m_Database.Get((int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y), UUID.Zero);
661 if (region == null)
662 {
663 MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y);
664 return;
665 }
666  
667 OutputRegionToConsole(region);
668 }
669  
670 private void OutputRegionToConsole(RegionData r)
671 {
672 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
673  
674 ConsoleDisplayList dispList = new ConsoleDisplayList();
675 dispList.AddRow("Region Name", r.RegionName);
676 dispList.AddRow("Region ID", r.RegionID);
677 dispList.AddRow("Location", string.Format("{0},{1}", r.coordX, r.coordY));
678 dispList.AddRow("URI", r.Data["serverURI"]);
679 dispList.AddRow("Owner ID", r.Data["owner_uuid"]);
680 dispList.AddRow("Flags", flags);
681  
682 MainConsole.Instance.Output(dispList.ToString());
683 }
684  
685 private void OutputRegionsToConsole(List<RegionData> regions)
686 {
687 foreach (RegionData r in regions)
688 OutputRegionToConsole(r);
689 }
690  
691 private void OutputRegionsToConsoleSummary(List<RegionData> regions)
692 {
693 ConsoleDisplayTable dispTable = new ConsoleDisplayTable();
694 dispTable.AddColumn("Name", 16);
695 dispTable.AddColumn("ID", 36);
696 dispTable.AddColumn("Position", 11);
697 dispTable.AddColumn("Owner ID", 36);
698 dispTable.AddColumn("Flags", 60);
699  
700 foreach (RegionData r in regions)
701 {
702 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
703 dispTable.AddRow(
704 r.RegionName,
705 r.RegionID.ToString(),
706 string.Format("{0},{1}", r.coordX, r.coordY),
707 r.Data["owner_uuid"].ToString(),
708 flags.ToString());
709 }
710  
711 MainConsole.Instance.Output(dispTable.ToString());
712 }
713  
714 private int ParseFlags(int prev, string flags)
715 {
716 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)prev;
717  
718 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
719  
720 foreach (string p in parts)
721 {
722 int val;
723  
724 try
725 {
726 if (p.StartsWith("+"))
727 {
728 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
729 f |= (OpenSim.Framework.RegionFlags)val;
730 }
731 else if (p.StartsWith("-"))
732 {
733 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
734 f &= ~(OpenSim.Framework.RegionFlags)val;
735 }
736 else
737 {
738 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p);
739 f |= (OpenSim.Framework.RegionFlags)val;
740 }
741 }
742 catch (Exception)
743 {
744 MainConsole.Instance.Output("Error in flag specification: " + p);
745 }
746 }
747  
748 return (int)f;
749 }
750  
751 private void HandleSetFlags(string module, string[] cmd)
752 {
753 if (cmd.Length < 5)
754 {
755 MainConsole.Instance.Output("Syntax: set region flags <region name> <flags>");
756 return;
757 }
758  
759 List<RegionData> regions = m_Database.Get(Util.EscapeForLike(cmd[3]), UUID.Zero);
760 if (regions == null || regions.Count < 1)
761 {
762 MainConsole.Instance.Output("Region not found");
763 return;
764 }
765  
766 foreach (RegionData r in regions)
767 {
768 int flags = Convert.ToInt32(r.Data["flags"]);
769 flags = ParseFlags(flags, cmd[4]);
770 r.Data["flags"] = flags.ToString();
771 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)flags;
772  
773 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f));
774 m_Database.Store(r);
775 }
776 }
777 }
778 }