diff options
author | UbitUmarov | 2015-09-01 11:43:07 +0100 |
---|---|---|
committer | UbitUmarov | 2015-09-01 11:43:07 +0100 |
commit | fb78b182520fc9bb0f971afd0322029c70278ea6 (patch) | |
tree | b4e30d383938fdeef8c92d1d1c2f44bb61d329bd /OpenSim/Framework/RegionInfo.cs | |
parent | lixo (diff) | |
parent | Mantis #7713: fixed bug introduced by 1st MOSES patch. (diff) | |
download | opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.zip opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.gz opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.bz2 opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.xz |
Merge remote-tracking branch 'os/master'
Diffstat (limited to 'OpenSim/Framework/RegionInfo.cs')
-rw-r--r-- | OpenSim/Framework/RegionInfo.cs | 1008 |
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Net; | ||
31 | using System.Net.Sockets; | ||
32 | using System.Reflection; | ||
33 | using System.Xml; | ||
34 | using System.IO; | ||
35 | using log4net; | ||
36 | using Nini.Config; | ||
37 | using OpenMetaverse; | ||
38 | using OpenMetaverse.StructuredData; | ||
39 | //using OpenSim.Framework.Console; | ||
40 | |||
41 | namespace 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 | } | ||