aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/RegionInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/RegionInfo.cs1008
1 files changed, 1008 insertions, 0 deletions
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
new file mode 100644
index 0000000..79fbd96
--- /dev/null
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -0,0 +1,1008 @@
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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Net.Sockets;
32using System.Reflection;
33using System.Xml;
34using System.IO;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39//using OpenSim.Framework.Console;
40
41namespace OpenSim.Framework
42{
43 public class RegionLightShareData : ICloneable
44 {
45 public bool valid = false;
46 public UUID regionID = UUID.Zero;
47 public Vector3 waterColor = new Vector3(4.0f,38.0f,64.0f);
48 public float waterFogDensityExponent = 4.0f;
49 public float underwaterFogModifier = 0.25f;
50 public Vector3 reflectionWaveletScale = new Vector3(2.0f,2.0f,2.0f);
51 public float fresnelScale = 0.40f;
52 public float fresnelOffset = 0.50f;
53 public float refractScaleAbove = 0.03f;
54 public float refractScaleBelow = 0.20f;
55 public float blurMultiplier = 0.040f;
56 public Vector2 bigWaveDirection = new Vector2(1.05f,-0.42f);
57 public Vector2 littleWaveDirection = new Vector2(1.11f,-1.16f);
58 public UUID normalMapTexture = new UUID("822ded49-9a6c-f61c-cb89-6df54f42cdf4");
59 public Vector4 horizon = new Vector4(0.25f, 0.25f, 0.32f, 0.32f);
60 public float hazeHorizon = 0.19f;
61 public Vector4 blueDensity = new Vector4(0.12f, 0.22f, 0.38f, 0.38f);
62 public float hazeDensity = 0.70f;
63 public float densityMultiplier = 0.18f;
64 public float distanceMultiplier = 0.8f;
65 public UInt16 maxAltitude = 1605;
66 public Vector4 sunMoonColor = new Vector4(0.24f, 0.26f, 0.30f, 0.30f);
67 public float sunMoonPosition = 0.317f;
68 public Vector4 ambient = new Vector4(0.35f,0.35f,0.35f,0.35f);
69 public float eastAngle = 0.0f;
70 public float sunGlowFocus = 0.10f;
71 public float sunGlowSize = 1.75f;
72 public float sceneGamma = 1.0f;
73 public float starBrightness = 0.0f;
74 public Vector4 cloudColor = new Vector4(0.41f, 0.41f, 0.41f, 0.41f);
75 public Vector3 cloudXYDensity = new Vector3(1.00f, 0.53f, 1.00f);
76 public float cloudCoverage = 0.27f;
77 public float cloudScale = 0.42f;
78 public Vector3 cloudDetailXYDensity = new Vector3(1.00f, 0.53f, 0.12f);
79 public float cloudScrollX = 0.20f;
80 public bool cloudScrollXLock = false;
81 public float cloudScrollY = 0.01f;
82 public bool cloudScrollYLock = false;
83 public bool drawClassicClouds = true;
84
85 public delegate void SaveDelegate(RegionLightShareData wl);
86 public event SaveDelegate OnSave;
87 public void Save()
88 {
89 if (OnSave != null)
90 OnSave(this);
91 }
92 public object Clone()
93 {
94 return this.MemberwiseClone(); // call clone method
95 }
96
97 }
98
99 public class RegionInfo
100 {
101 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
102 private static readonly string LogHeader = "[REGION INFO]";
103
104 public string RegionFile = String.Empty;
105 public bool isSandbox = false;
106 public bool Persistent = true;
107
108 private EstateSettings m_estateSettings;
109 private RegionSettings m_regionSettings;
110 // private IConfigSource m_configSource = null;
111
112 public UUID originRegionID = UUID.Zero;
113 public string proxyUrl = "";
114 public int ProxyOffset = 0;
115 public string regionSecret = UUID.Random().ToString();
116
117 public string osSecret;
118
119 public UUID lastMapUUID = UUID.Zero;
120 public string lastMapRefresh = "0";
121
122 private float m_nonphysPrimMin = 0;
123 private int m_nonphysPrimMax = 0;
124 private float m_physPrimMin = 0;
125 private int m_physPrimMax = 0;
126 private bool m_clampPrimSize = false;
127 private int m_objectCapacity = 0;
128 private int m_maxPrimsPerUser = -1;
129 private int m_linksetCapacity = 0;
130 private string m_regionType = String.Empty;
131 private RegionLightShareData m_windlight = new RegionLightShareData();
132 protected uint m_httpPort;
133 protected string m_serverURI;
134 protected string m_regionName = String.Empty;
135 protected bool Allow_Alternate_Ports;
136 public bool m_allow_alternate_ports;
137 protected string m_externalHostName;
138 protected IPEndPoint m_internalEndPoint;
139 protected uint m_remotingPort;
140 public UUID RegionID = UUID.Zero;
141 public string RemotingAddress;
142 public UUID ScopeID = UUID.Zero;
143 private UUID m_maptileStaticUUID = UUID.Zero;
144
145 public uint WorldLocX = 0;
146 public uint WorldLocY = 0;
147 public uint WorldLocZ = 0;
148
149 /// <summary>
150 /// X dimension of the region.
151 /// </summary>
152 /// <remarks>
153 /// If this is a varregion then the default size set here will be replaced when we load the region config.
154 /// </remarks>
155 public uint RegionSizeX = Constants.RegionSize;
156
157 /// <summary>
158 /// X dimension of the region.
159 /// </summary>
160 /// <remarks>
161 /// If this is a varregion then the default size set here will be replaced when we load the region config.
162 /// </remarks>
163 public uint RegionSizeY = Constants.RegionSize;
164
165 /// <summary>
166 /// Z dimension of the region.
167 /// </summary>
168 /// <remarks>
169 /// XXX: Unknown if this accounts for regions with negative Z.
170 /// </remarks>
171 public uint RegionSizeZ = Constants.RegionHeight;
172
173 private Dictionary<String, String> m_extraSettings = new Dictionary<string, string>();
174
175 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
176
177 // MT: Yes. Estates can't span trust boundaries. Therefore, it can be
178 // assumed that all instances belonging to one estate are able to
179 // access the same database server. Since estate settings are lodaed
180 // from there, that should be sufficient for full remote administration
181
182 // File based loading
183 //
184 public RegionInfo(string description, string filename, bool skipConsoleConfig, IConfigSource configSource) : this(description, filename, skipConsoleConfig, configSource, String.Empty)
185 {
186 }
187
188 public RegionInfo(string description, string filename, bool skipConsoleConfig, IConfigSource configSource, string configName)
189 {
190 // m_configSource = configSource;
191
192 if (filename.ToLower().EndsWith(".ini"))
193 {
194 if (!File.Exists(filename)) // New region config request
195 {
196 IniConfigSource newFile = new IniConfigSource();
197 ReadNiniConfig(newFile, configName);
198
199 newFile.Save(filename);
200
201 RegionFile = filename;
202
203 return;
204 }
205
206 IniConfigSource source = new IniConfigSource(filename);
207
208 bool saveFile = false;
209 if (source.Configs[configName] == null)
210 saveFile = true;
211
212 ReadNiniConfig(source, configName);
213
214 if (configName != String.Empty && saveFile)
215 source.Save(filename);
216
217 RegionFile = filename;
218
219 return;
220 }
221
222 try
223 {
224 // This will throw if it's not legal Nini XML format
225 //
226 IConfigSource xmlsource = new XmlConfigSource(filename);
227
228 ReadNiniConfig(xmlsource, configName);
229
230 RegionFile = filename;
231
232 return;
233 }
234 catch (Exception)
235 {
236 }
237 }
238
239 // The web loader uses this
240 //
241 public RegionInfo(string description, XmlNode xmlNode, bool skipConsoleConfig, IConfigSource configSource)
242 {
243 XmlElement elem = (XmlElement)xmlNode;
244 string name = elem.GetAttribute("Name");
245 string xmlstr = "<Nini>" + xmlNode.OuterXml + "</Nini>";
246 XmlConfigSource source = new XmlConfigSource(XmlReader.Create(new StringReader(xmlstr)));
247 ReadNiniConfig(source, name);
248
249 m_serverURI = string.Empty;
250 }
251
252 public RegionInfo(uint legacyRegionLocX, uint legacyRegionLocY, IPEndPoint internalEndPoint, string externalUri)
253 {
254 RegionLocX = legacyRegionLocX;
255 RegionLocY = legacyRegionLocY;
256 RegionSizeX = Constants.RegionSize;
257 RegionSizeY = Constants.RegionSize;
258 m_internalEndPoint = internalEndPoint;
259 m_externalHostName = externalUri;
260 m_serverURI = string.Empty;
261 }
262
263 public RegionInfo()
264 {
265 m_serverURI = string.Empty;
266 }
267
268 public EstateSettings EstateSettings
269 {
270 get
271 {
272 if (m_estateSettings == null)
273 {
274 m_estateSettings = new EstateSettings();
275 }
276
277 return m_estateSettings;
278 }
279
280 set { m_estateSettings = value; }
281 }
282
283 public RegionSettings RegionSettings
284 {
285 get
286 {
287 if (m_regionSettings == null)
288 {
289 m_regionSettings = new RegionSettings();
290 }
291
292 return m_regionSettings;
293 }
294
295 set { m_regionSettings = value; }
296 }
297
298 public RegionLightShareData WindlightSettings
299 {
300 get
301 {
302 if (m_windlight == null)
303 {
304 m_windlight = new RegionLightShareData();
305 }
306
307 return m_windlight;
308 }
309
310 set { m_windlight = value; }
311 }
312
313 public float NonphysPrimMin
314 {
315 get { return m_nonphysPrimMin; }
316 }
317
318 public int NonphysPrimMax
319 {
320 get { return m_nonphysPrimMax; }
321 }
322
323 public float PhysPrimMin
324 {
325 get { return m_physPrimMin; }
326 }
327
328 public int PhysPrimMax
329 {
330 get { return m_physPrimMax; }
331 }
332
333 public bool ClampPrimSize
334 {
335 get { return m_clampPrimSize; }
336 }
337
338 public int ObjectCapacity
339 {
340 get { return m_objectCapacity; }
341 }
342
343 public int MaxPrimsPerUser
344 {
345 get { return m_maxPrimsPerUser; }
346 }
347
348 public int LinksetCapacity
349 {
350 get { return m_linksetCapacity; }
351 }
352
353 public int AgentCapacity { get; set; }
354
355 public byte AccessLevel
356 {
357 get { return (byte)Util.ConvertMaturityToAccessLevel((uint)RegionSettings.Maturity); }
358 }
359
360 public string RegionType
361 {
362 get { return m_regionType; }
363 }
364
365 public UUID MaptileStaticUUID
366 {
367 get { return m_maptileStaticUUID; }
368 }
369
370 public string MaptileStaticFile { get; private set; }
371
372 /// <summary>
373 /// The port by which http communication occurs with the region (most noticeably, CAPS communication)
374 /// </summary>
375 public uint HttpPort
376 {
377 get { return m_httpPort; }
378 set { m_httpPort = value; }
379 }
380
381 /// <summary>
382 /// A well-formed URI for the host region server (namely "http://" + ExternalHostName)
383 /// </summary>
384
385 public string ServerURI
386 {
387 get {
388 if ( m_serverURI != string.Empty ) {
389 return m_serverURI;
390 } else {
391 return "http://" + m_externalHostName + ":" + m_httpPort + "/";
392 }
393 }
394 set {
395 if ( value.EndsWith("/") ) {
396 m_serverURI = value;
397 } else {
398 m_serverURI = value + '/';
399 }
400 }
401 }
402
403 public string RegionName
404 {
405 get { return m_regionName; }
406 set { m_regionName = value; }
407 }
408
409 public uint RemotingPort
410 {
411 get { return m_remotingPort; }
412 set { m_remotingPort = value; }
413 }
414
415 /// <value>
416 /// This accessor can throw all the exceptions that Dns.GetHostAddresses can throw.
417 ///
418 /// XXX Isn't this really doing too much to be a simple getter, rather than an explict method?
419 /// </value>
420 public IPEndPoint ExternalEndPoint
421 {
422 get
423 {
424 // Old one defaults to IPv6
425 //return new IPEndPoint(Dns.GetHostAddresses(m_externalHostName)[0], m_internalEndPoint.Port);
426
427 IPAddress ia = null;
428 // If it is already an IP, don't resolve it - just return directly
429 if (IPAddress.TryParse(m_externalHostName, out ia))
430 return new IPEndPoint(ia, m_internalEndPoint.Port);
431
432 // Reset for next check
433 ia = null;
434 try
435 {
436 foreach (IPAddress Adr in Dns.GetHostAddresses(m_externalHostName))
437 {
438 if (ia == null)
439 ia = Adr;
440
441 if (Adr.AddressFamily == AddressFamily.InterNetwork)
442 {
443 ia = Adr;
444 break;
445 }
446 }
447 }
448 catch (SocketException e)
449 {
450 throw new Exception(
451 "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" +
452 e + "' attached to this exception", e);
453 }
454
455 return new IPEndPoint(ia, m_internalEndPoint.Port);
456 }
457
458 set { m_externalHostName = value.ToString(); }
459 }
460
461 public string ExternalHostName
462 {
463 get { return m_externalHostName; }
464 set { m_externalHostName = value; }
465 }
466
467 public IPEndPoint InternalEndPoint
468 {
469 get { return m_internalEndPoint; }
470 set { m_internalEndPoint = value; }
471 }
472
473 /// <summary>
474 /// The x co-ordinate of this region in map tiles (e.g. 1000).
475 /// Coordinate is scaled as world coordinates divided by the legacy region size
476 /// and is thus is the number of legacy regions.
477 /// </summary>
478 public uint RegionLocX
479 {
480 get { return WorldLocX / Constants.RegionSize; }
481 set { WorldLocX = value * Constants.RegionSize; }
482 }
483
484 /// <summary>
485 /// The y co-ordinate of this region in map tiles (e.g. 1000).
486 /// Coordinate is scaled as world coordinates divided by the legacy region size
487 /// and is thus is the number of legacy regions.
488 /// </summary>
489 public uint RegionLocY
490 {
491 get { return WorldLocY / Constants.RegionSize; }
492 set { WorldLocY = value * Constants.RegionSize; }
493 }
494
495 public void SetDefaultRegionSize()
496 {
497 WorldLocX = 0;
498 WorldLocY = 0;
499 WorldLocZ = 0;
500 RegionSizeX = Constants.RegionSize;
501 RegionSizeY = Constants.RegionSize;
502 RegionSizeZ = Constants.RegionHeight;
503 }
504
505 // A unique region handle is created from the region's world coordinates.
506 // This cannot be changed because some code expects to receive the region handle and then
507 // compute the region coordinates from it.
508 public ulong RegionHandle
509 {
510 get { return Util.UIntsToLong(WorldLocX, WorldLocY); }
511 }
512
513 public void SetEndPoint(string ipaddr, int port)
514 {
515 IPAddress tmpIP = IPAddress.Parse(ipaddr);
516 IPEndPoint tmpEPE = new IPEndPoint(tmpIP, port);
517 m_internalEndPoint = tmpEPE;
518 }
519
520 public string GetSetting(string key)
521 {
522 string val;
523 string keylower = key.ToLower();
524 if (m_extraSettings.TryGetValue(keylower, out val))
525 return val;
526 m_log.DebugFormat("[RegionInfo] Could not locate value for parameter {0}", key);
527 return null;
528 }
529
530 private void SetExtraSetting(string key, string value)
531 {
532 string keylower = key.ToLower();
533 m_extraSettings[keylower] = value;
534 }
535
536 private void ReadNiniConfig(IConfigSource source, string name)
537 {
538// bool creatingNew = false;
539
540 if (source.Configs.Count == 0)
541 {
542 MainConsole.Instance.Output("=====================================\n");
543 MainConsole.Instance.Output("We are now going to ask a couple of questions about your region.\n");
544 MainConsole.Instance.Output("You can press 'enter' without typing anything to use the default\n");
545 MainConsole.Instance.Output("the default is displayed between [ ] brackets.\n");
546 MainConsole.Instance.Output("=====================================\n");
547
548 if (name == String.Empty)
549 {
550 while (name.Trim() == string.Empty)
551 {
552 name = MainConsole.Instance.CmdPrompt("New region name", name);
553 if (name.Trim() == string.Empty)
554 {
555 MainConsole.Instance.Output("Cannot interactively create region with no name");
556 }
557 }
558 }
559
560 source.AddConfig(name);
561
562// creatingNew = true;
563 }
564
565 if (name == String.Empty)
566 name = source.Configs[0].Name;
567
568 if (source.Configs[name] == null)
569 {
570 source.AddConfig(name);
571 }
572
573 RegionName = name;
574 IConfig config = source.Configs[name];
575
576 // Track all of the keys in this config and remove as they are processed
577 // The remaining keys will be added to generic key-value storage for
578 // whoever might need it
579 HashSet<String> allKeys = new HashSet<String>();
580 foreach (string s in config.GetKeys())
581 {
582 allKeys.Add(s);
583 }
584
585 // RegionUUID
586 //
587 allKeys.Remove("RegionUUID");
588 string regionUUID = config.GetString("RegionUUID", string.Empty);
589 if (!UUID.TryParse(regionUUID.Trim(), out RegionID))
590 {
591 UUID newID = UUID.Random();
592 while (RegionID == UUID.Zero)
593 {
594 regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString());
595 if (!UUID.TryParse(regionUUID.Trim(), out RegionID))
596 {
597 MainConsole.Instance.Output("RegionUUID must be a valid UUID");
598 }
599 }
600 config.Set("RegionUUID", regionUUID);
601 }
602
603 originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?)
604
605 // Location
606 //
607 allKeys.Remove("Location");
608 string location = config.GetString("Location", String.Empty);
609 if (location == String.Empty)
610 {
611 location = MainConsole.Instance.CmdPrompt("Region Location", "1000,1000");
612 config.Set("Location", location);
613 }
614
615 string[] locationElements = location.Split(new char[] {','});
616
617 RegionLocX = Convert.ToUInt32(locationElements[0]);
618 RegionLocY = Convert.ToUInt32(locationElements[1]);
619
620 // Region size
621 // Default to legacy region size if not specified.
622 allKeys.Remove("SizeX");
623 string configSizeX = config.GetString("SizeX", Constants.RegionSize.ToString());
624 config.Set("SizeX", configSizeX);
625 RegionSizeX = Convert.ToUInt32(configSizeX);
626 allKeys.Remove("SizeY");
627 string configSizeY = config.GetString("SizeY", Constants.RegionSize.ToString());
628 config.Set("SizeY", configSizeX);
629 RegionSizeY = Convert.ToUInt32(configSizeY);
630 allKeys.Remove("SizeZ");
631 string configSizeZ = config.GetString("SizeZ", Constants.RegionHeight.ToString());
632 config.Set("SizeZ", configSizeX);
633 RegionSizeZ = Convert.ToUInt32(configSizeZ);
634
635 DoRegionSizeSanityChecks();
636
637 // InternalAddress
638 //
639 IPAddress address;
640 allKeys.Remove("InternalAddress");
641 if (config.Contains("InternalAddress"))
642 {
643 address = IPAddress.Parse(config.GetString("InternalAddress", String.Empty));
644 }
645 else
646 {
647 address = IPAddress.Parse(MainConsole.Instance.CmdPrompt("Internal IP address", "0.0.0.0"));
648 config.Set("InternalAddress", address.ToString());
649 }
650
651 // InternalPort
652 //
653 int port;
654 allKeys.Remove("InternalPort");
655 if (config.Contains("InternalPort"))
656 {
657 port = config.GetInt("InternalPort", 9000);
658 }
659 else
660 {
661 port = Convert.ToInt32(MainConsole.Instance.CmdPrompt("Internal port", "9000"));
662 config.Set("InternalPort", port);
663 }
664 m_internalEndPoint = new IPEndPoint(address, port);
665
666 // AllowAlternatePorts
667 //
668 allKeys.Remove("AllowAlternatePorts");
669 if (config.Contains("AllowAlternatePorts"))
670 {
671 m_allow_alternate_ports = config.GetBoolean("AllowAlternatePorts", true);
672 }
673 else
674 {
675 m_allow_alternate_ports = Convert.ToBoolean(MainConsole.Instance.CmdPrompt("Allow alternate ports", "False"));
676
677 config.Set("AllowAlternatePorts", m_allow_alternate_ports.ToString());
678 }
679
680 // ExternalHostName
681 //
682 allKeys.Remove("ExternalHostName");
683 string externalName;
684 if (config.Contains("ExternalHostName"))
685 {
686 externalName = config.GetString("ExternalHostName", "SYSTEMIP");
687 }
688 else
689 {
690 externalName = MainConsole.Instance.CmdPrompt("External host name", "SYSTEMIP");
691 config.Set("ExternalHostName", externalName);
692 }
693 if (externalName == "SYSTEMIP")
694 {
695 m_externalHostName = Util.GetLocalHost().ToString();
696 m_log.InfoFormat(
697 "[REGIONINFO]: Resolving SYSTEMIP to {0} for external hostname of region {1}",
698 m_externalHostName, name);
699 }
700 else
701 {
702 m_externalHostName = externalName;
703 }
704
705 // RegionType
706 m_regionType = config.GetString("RegionType", String.Empty);
707 allKeys.Remove("RegionType");
708
709 #region Prim and map stuff
710
711 m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0);
712 allKeys.Remove("NonPhysicalPrimMin");
713
714 m_nonphysPrimMax = config.GetInt("NonPhysicalPrimMax", 0);
715 allKeys.Remove("NonPhysicalPrimMax");
716
717 m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0);
718 allKeys.Remove("PhysicalPrimMin");
719
720 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0);
721 allKeys.Remove("PhysicalPrimMax");
722
723 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false);
724 allKeys.Remove("ClampPrimSize");
725
726 m_objectCapacity = config.GetInt("MaxPrims", 15000);
727 allKeys.Remove("MaxPrims");
728
729 m_maxPrimsPerUser = config.GetInt("MaxPrimsPerUser", -1);
730 allKeys.Remove("MaxPrimsPerUser");
731
732 m_linksetCapacity = config.GetInt("LinksetPrims", 0);
733 allKeys.Remove("LinksetPrims");
734
735 allKeys.Remove("MaptileStaticUUID");
736 string mapTileStaticUUID = config.GetString("MaptileStaticUUID", UUID.Zero.ToString());
737 if (UUID.TryParse(mapTileStaticUUID.Trim(), out m_maptileStaticUUID))
738 {
739 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
740 }
741
742 MaptileStaticFile = config.GetString("MaptileStaticFile", String.Empty);
743 allKeys.Remove("MaptileStaticFile");
744
745 #endregion
746
747 AgentCapacity = config.GetInt("MaxAgents", 100);
748 allKeys.Remove("MaxAgents");
749
750 // Multi-tenancy
751 //
752 ScopeID = new UUID(config.GetString("ScopeID", UUID.Zero.ToString()));
753 allKeys.Remove("ScopeID");
754
755 foreach (String s in allKeys)
756 {
757 SetExtraSetting(s, config.GetString(s));
758 }
759 }
760
761 // Make sure user specified region sizes are sane.
762 // Must be multiples of legacy region size (256).
763 private void DoRegionSizeSanityChecks()
764 {
765 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
766 {
767 // Doing non-legacy region sizes.
768 // Enforce region size to be multiples of the legacy region size (256)
769 uint partial = RegionSizeX % Constants.RegionSize;
770 if (partial != 0)
771 {
772 RegionSizeX -= partial;
773 if (RegionSizeX == 0)
774 RegionSizeX = Constants.RegionSize;
775 m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeX={3} instead of specified {4}",
776 LogHeader, Constants.RegionSize, m_regionName, RegionSizeX, RegionSizeX + partial);
777 }
778 partial = RegionSizeY % Constants.RegionSize;
779 if (partial != 0)
780 {
781 RegionSizeY -= partial;
782 if (RegionSizeY == 0)
783 RegionSizeY = Constants.RegionSize;
784 m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeY={3} instead of specified {4}",
785 LogHeader, Constants.RegionSize, m_regionName, RegionSizeY, RegionSizeY + partial);
786 }
787
788 // Because of things in the viewer, regions MUST be square.
789 // Remove this check when viewers have been updated.
790 if (RegionSizeX != RegionSizeY)
791 {
792 uint minSize = Math.Min(RegionSizeX, RegionSizeY);
793 RegionSizeX = minSize;
794 RegionSizeY = minSize;
795 m_log.ErrorFormat("{0} Regions must be square until viewers are updated. Forcing region {1} size to <{2},{3}>",
796 LogHeader, m_regionName, RegionSizeX, RegionSizeY);
797 }
798
799 // There is a practical limit to region size.
800 if (RegionSizeX > Constants.MaximumRegionSize || RegionSizeY > Constants.MaximumRegionSize)
801 {
802 RegionSizeX = Util.Clamp<uint>(RegionSizeX, Constants.RegionSize, Constants.MaximumRegionSize);
803 RegionSizeY = Util.Clamp<uint>(RegionSizeY, Constants.RegionSize, Constants.MaximumRegionSize);
804 m_log.ErrorFormat("{0} Region dimensions must be less than {1}. Clamping {2}'s size to <{3},{4}>",
805 LogHeader, Constants.MaximumRegionSize, m_regionName, RegionSizeX, RegionSizeY);
806 }
807
808 m_log.InfoFormat("{0} Region {1} size set to <{2},{3}>", LogHeader, m_regionName, RegionSizeX, RegionSizeY);
809 }
810 }
811
812 private void WriteNiniConfig(IConfigSource source)
813 {
814 IConfig config = source.Configs[RegionName];
815
816 if (config != null)
817 source.Configs.Remove(config);
818
819 config = source.AddConfig(RegionName);
820
821 config.Set("RegionUUID", RegionID.ToString());
822
823 string location = String.Format("{0},{1}", RegionLocX, RegionLocY);
824 config.Set("Location", location);
825
826 if (RegionSizeX > 0)
827 config.Set("SizeX", RegionSizeX);
828
829 if (RegionSizeY > 0)
830 config.Set("SizeY", RegionSizeY);
831
832// if (RegionSizeZ > 0)
833// config.Set("SizeZ", RegionSizeZ);
834
835 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
836 config.Set("InternalPort", m_internalEndPoint.Port);
837
838 config.Set("AllowAlternatePorts", m_allow_alternate_ports.ToString());
839
840 config.Set("ExternalHostName", m_externalHostName);
841
842 if (m_nonphysPrimMin > 0)
843 config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
844
845 if (m_nonphysPrimMax > 0)
846 config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
847
848 if (m_physPrimMin > 0)
849 config.Set("PhysicalPrimMax", m_physPrimMin);
850
851 if (m_physPrimMax > 0)
852 config.Set("PhysicalPrimMax", m_physPrimMax);
853
854 config.Set("ClampPrimSize", m_clampPrimSize.ToString());
855
856 if (m_objectCapacity > 0)
857 config.Set("MaxPrims", m_objectCapacity);
858
859 if (m_maxPrimsPerUser > -1)
860 config.Set("MaxPrimsPerUser", m_maxPrimsPerUser);
861
862 if (m_linksetCapacity > 0)
863 config.Set("LinksetPrims", m_linksetCapacity);
864
865 if (AgentCapacity > 0)
866 config.Set("MaxAgents", AgentCapacity);
867
868 if (ScopeID != UUID.Zero)
869 config.Set("ScopeID", ScopeID.ToString());
870
871 if (RegionType != String.Empty)
872 config.Set("RegionType", RegionType);
873
874 if (m_maptileStaticUUID != UUID.Zero)
875 config.Set("MaptileStaticUUID", m_maptileStaticUUID.ToString());
876
877 if (MaptileStaticFile != null && MaptileStaticFile != String.Empty)
878 config.Set("MaptileStaticFile", MaptileStaticFile);
879 }
880
881 public void SaveRegionToFile(string description, string filename)
882 {
883 if (filename.ToLower().EndsWith(".ini"))
884 {
885 IniConfigSource source = new IniConfigSource();
886 try
887 {
888 source = new IniConfigSource(filename); // Load if it exists
889 }
890 catch (Exception)
891 {
892 }
893
894 WriteNiniConfig(source);
895
896 source.Save(filename);
897
898 return;
899 }
900 else
901 throw new Exception("Invalid file type for region persistence.");
902 }
903
904 public void SaveLastMapUUID(UUID mapUUID)
905 {
906 lastMapUUID = mapUUID;
907 lastMapRefresh = Util.UnixTimeSinceEpoch().ToString();
908 }
909
910 public OSDMap PackRegionInfoData()
911 {
912 OSDMap args = new OSDMap();
913 args["region_id"] = OSD.FromUUID(RegionID);
914 if ((RegionName != null) && !RegionName.Equals(""))
915 args["region_name"] = OSD.FromString(RegionName);
916 args["external_host_name"] = OSD.FromString(ExternalHostName);
917 args["http_port"] = OSD.FromString(HttpPort.ToString());
918 args["server_uri"] = OSD.FromString(ServerURI);
919
920 args["region_xloc"] = OSD.FromString(RegionLocX.ToString());
921 args["region_yloc"] = OSD.FromString(RegionLocY.ToString());
922 args["region_size_x"] = OSD.FromString(RegionSizeX.ToString());
923 args["region_size_y"] = OSD.FromString(RegionSizeY.ToString());
924 args["region_size_z"] = OSD.FromString(RegionSizeZ.ToString());
925
926 args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString());
927 args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString());
928 if ((RemotingAddress != null) && !RemotingAddress.Equals(""))
929 args["remoting_address"] = OSD.FromString(RemotingAddress);
930 args["remoting_port"] = OSD.FromString(RemotingPort.ToString());
931 args["allow_alt_ports"] = OSD.FromBoolean(m_allow_alternate_ports);
932 if ((proxyUrl != null) && !proxyUrl.Equals(""))
933 args["proxy_url"] = OSD.FromString(proxyUrl);
934 if (RegionType != String.Empty)
935 args["region_type"] = OSD.FromString(RegionType);
936
937 return args;
938 }
939
940 public void UnpackRegionInfoData(OSDMap args)
941 {
942 if (args["region_id"] != null)
943 RegionID = args["region_id"].AsUUID();
944 if (args["region_name"] != null)
945 RegionName = args["region_name"].AsString();
946 if (args["external_host_name"] != null)
947 ExternalHostName = args["external_host_name"].AsString();
948 if (args["http_port"] != null)
949 UInt32.TryParse(args["http_port"].AsString(), out m_httpPort);
950 if (args["server_uri"] != null)
951 ServerURI = args["server_uri"].AsString();
952 if (args["region_xloc"] != null)
953 {
954 uint locx;
955 UInt32.TryParse(args["region_xloc"].AsString(), out locx);
956 RegionLocX = locx;
957 }
958 if (args["region_yloc"] != null)
959 {
960 uint locy;
961 UInt32.TryParse(args["region_yloc"].AsString(), out locy);
962 RegionLocY = locy;
963 }
964 if (args.ContainsKey("region_size_x"))
965 RegionSizeX = (uint)args["region_size_x"].AsInteger();
966 if (args.ContainsKey("region_size_y"))
967 RegionSizeY = (uint)args["region_size_y"].AsInteger();
968 if (args.ContainsKey("region_size_z"))
969 RegionSizeZ = (uint)args["region_size_z"].AsInteger();
970
971 IPAddress ip_addr = null;
972 if (args["internal_ep_address"] != null)
973 {
974 IPAddress.TryParse(args["internal_ep_address"].AsString(), out ip_addr);
975 }
976 int port = 0;
977 if (args["internal_ep_port"] != null)
978 {
979 Int32.TryParse(args["internal_ep_port"].AsString(), out port);
980 }
981 InternalEndPoint = new IPEndPoint(ip_addr, port);
982 if (args["remoting_address"] != null)
983 RemotingAddress = args["remoting_address"].AsString();
984 if (args["remoting_port"] != null)
985 UInt32.TryParse(args["remoting_port"].AsString(), out m_remotingPort);
986 if (args["allow_alt_ports"] != null)
987 m_allow_alternate_ports = args["allow_alt_ports"].AsBoolean();
988 if (args["proxy_url"] != null)
989 proxyUrl = args["proxy_url"].AsString();
990 if (args["region_type"] != null)
991 m_regionType = args["region_type"].AsString();
992 }
993
994 public static RegionInfo Create(UUID regionID, string regionName, uint regX, uint regY, string externalHostName, uint httpPort, uint simPort, uint remotingPort, string serverURI)
995 {
996 RegionInfo regionInfo;
997 IPEndPoint neighbourInternalEndPoint = new IPEndPoint(Util.GetHostFromDNS(externalHostName), (int)simPort);
998 regionInfo = new RegionInfo(regX, regY, neighbourInternalEndPoint, externalHostName);
999 regionInfo.RemotingPort = remotingPort;
1000 regionInfo.RemotingAddress = externalHostName;
1001 regionInfo.HttpPort = httpPort;
1002 regionInfo.RegionID = regionID;
1003 regionInfo.RegionName = regionName;
1004 regionInfo.ServerURI = serverURI;
1005 return regionInfo;
1006 }
1007 }
1008}