aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs')
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs878
1 files changed, 878 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
new file mode 100644
index 0000000..98b0ae1
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
@@ -0,0 +1,878 @@
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.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Framework.Client;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Framework.Console;
39using OpenSim.Region.PhysicsModules.SharedBase;
40using Mono.Addins;
41
42namespace OpenSim.Region.RegionCombinerModule
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionCombinerModule")]
45 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48// private static string LogHeader = "[REGION COMBINER MODULE]";
49
50 public string Name
51 {
52 get { return "RegionCombinerModule"; }
53 }
54
55 public Type ReplaceableInterface
56 {
57 get { return null; }
58 }
59
60 /// <summary>
61 /// Is this module enabled?
62 /// </summary>
63 private bool m_combineContiguousRegions = false;
64
65 /// <summary>
66 /// This holds the root regions for the megaregions.
67 /// </summary>
68 /// <remarks>
69 /// Usually there is only ever one megaregion (and hence only one entry here).
70 /// </remarks>
71 private Dictionary<UUID, RegionConnections> m_regions = new Dictionary<UUID, RegionConnections>();
72
73 /// <summary>
74 /// The scenes that comprise the megaregion.
75 /// </summary>
76 private Dictionary<UUID, Scene> m_startingScenes = new Dictionary<UUID, Scene>();
77
78 public void Initialise(IConfigSource source)
79 {
80 IConfig myConfig = source.Configs["Startup"];
81 m_combineContiguousRegions = myConfig.GetBoolean("CombineContiguousRegions", false);
82
83 MainConsole.Instance.Commands.AddCommand(
84 "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms",
85 "Fixes phantom objects after an import to a megaregion or a change from a megaregion back to normal regions",
86 FixPhantoms);
87 }
88
89 public void Close()
90 {
91 }
92
93 public void AddRegion(Scene scene)
94 {
95 if (m_combineContiguousRegions)
96 scene.RegisterModuleInterface<IRegionCombinerModule>(this);
97 }
98
99 public void RemoveRegion(Scene scene)
100 {
101 lock (m_startingScenes)
102 m_startingScenes.Remove(scene.RegionInfo.originRegionID);
103 }
104
105 public void RegionLoaded(Scene scene)
106 {
107 lock (m_startingScenes)
108 m_startingScenes.Add(scene.RegionInfo.originRegionID, scene);
109
110 if (m_combineContiguousRegions)
111 {
112 RegionLoadedDoWork(scene);
113
114 scene.EventManager.OnNewPresence += NewPresence;
115 }
116 }
117
118 public bool IsRootForMegaregion(UUID regionId)
119 {
120 lock (m_regions)
121 return m_regions.ContainsKey(regionId);
122 }
123
124 public Vector2 GetSizeOfMegaregion(UUID regionId)
125 {
126 lock (m_regions)
127 {
128 if (m_regions.ContainsKey(regionId))
129 {
130 RegionConnections rootConn = m_regions[regionId];
131
132 return new Vector2((float)rootConn.XEnd, (float)rootConn.YEnd);
133 }
134 }
135
136 throw new Exception(string.Format("Region with id {0} not found", regionId));
137 }
138
139 // Test to see if this postiion (relative to the region) is within the area covered
140 // by this megaregion.
141 public bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy)
142 {
143 bool ret = false;
144 if (xx < 0 || yy < 0)
145 return ret;
146
147 foreach (RegionConnections rootRegion in m_regions.Values)
148 {
149 if (currentRegion == rootRegion.RegionId)
150 {
151 // The caller is in the root region so this is an easy test
152 if (xx < rootRegion.XEnd && yy < rootRegion.YEnd)
153 {
154 ret = true;
155 }
156 break;
157 }
158 else
159 {
160 // Maybe the caller is in one of the sub-regions
161 foreach (RegionData childRegion in rootRegion.ConnectedRegions)
162 {
163 if (currentRegion == childRegion.RegionId)
164 {
165 // This is a child. Diddle the offsets and check if in
166 Vector3 positionInMegaregion = childRegion.Offset;
167 positionInMegaregion.X += xx;
168 positionInMegaregion.Y += yy;
169 if (positionInMegaregion.X < rootRegion.XEnd && positionInMegaregion.Y < rootRegion.YEnd)
170 {
171 ret = true;
172 }
173 break;
174 }
175 }
176 }
177 }
178
179 return ret;
180 }
181
182 private void NewPresence(ScenePresence presence)
183 {
184 if (presence.IsChildAgent)
185 {
186 byte[] throttleData;
187
188 try
189 {
190 throttleData = presence.ControllingClient.GetThrottlesPacked(1);
191 }
192 catch (NotImplementedException)
193 {
194 return;
195 }
196
197 if (throttleData == null)
198 return;
199
200 if (throttleData.Length == 0)
201 return;
202
203 if (throttleData.Length != 28)
204 return;
205
206 byte[] adjData;
207 int pos = 0;
208
209 if (!BitConverter.IsLittleEndian)
210 {
211 byte[] newData = new byte[7 * 4];
212 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
213
214 for (int i = 0; i < 7; i++)
215 Array.Reverse(newData, i * 4, 4);
216
217 adjData = newData;
218 }
219 else
220 {
221 adjData = throttleData;
222 }
223
224 // 0.125f converts from bits to bytes
225 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
226 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
227 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
228 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
229 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
230 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
231 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
232 // State is a subcategory of task that we allocate a percentage to
233
234
235 //int total = resend + land + wind + cloud + task + texture + asset;
236
237 byte[] data = new byte[7 * 4];
238 int ii = 0;
239
240 Buffer.BlockCopy(Utils.FloatToBytes(resend), 0, data, ii, 4); ii += 4;
241 Buffer.BlockCopy(Utils.FloatToBytes(land * 50), 0, data, ii, 4); ii += 4;
242 Buffer.BlockCopy(Utils.FloatToBytes(wind), 0, data, ii, 4); ii += 4;
243 Buffer.BlockCopy(Utils.FloatToBytes(cloud), 0, data, ii, 4); ii += 4;
244 Buffer.BlockCopy(Utils.FloatToBytes(task), 0, data, ii, 4); ii += 4;
245 Buffer.BlockCopy(Utils.FloatToBytes(texture), 0, data, ii, 4); ii += 4;
246 Buffer.BlockCopy(Utils.FloatToBytes(asset), 0, data, ii, 4);
247
248 try
249 {
250 presence.ControllingClient.SetChildAgentThrottle(data);
251 }
252 catch (NotImplementedException)
253 {
254 return;
255 }
256 }
257 }
258
259 private void RegionLoadedDoWork(Scene scene)
260 {
261/*
262 // For testing on a single instance
263 if (scene.RegionInfo.RegionLocX == 1004 && scene.RegionInfo.RegionLocY == 1000)
264 return;
265 //
266*/
267
268 RegionConnections newConn = new RegionConnections();
269 newConn.ConnectedRegions = new List<RegionData>();
270 newConn.RegionScene = scene;
271 newConn.RegionLandChannel = scene.LandChannel;
272 newConn.RegionId = scene.RegionInfo.originRegionID;
273 newConn.X = scene.RegionInfo.RegionLocX;
274 newConn.Y = scene.RegionInfo.RegionLocY;
275 newConn.XEnd = scene.RegionInfo.RegionSizeX;
276 newConn.YEnd = scene.RegionInfo.RegionSizeX;
277
278 lock (m_regions)
279 {
280 bool connectedYN = false;
281
282 foreach (RegionConnections rootConn in m_regions.Values)
283 {
284 #region commented
285 /*
286 // If we're one region over +x +y
287 //xxy
288 //xxx
289 //xxx
290 if ((((int)conn.X * (int)Constants.RegionSize) + conn.XEnd
291 == (regionConnections.X * (int)Constants.RegionSize))
292 && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
293 == (regionConnections.Y * (int)Constants.RegionSize)))
294 {
295 Vector3 offset = Vector3.Zero;
296 offset.X = (((regionConnections.X * (int) Constants.RegionSize)) -
297 ((conn.X * (int) Constants.RegionSize)));
298 offset.Y = (((regionConnections.Y * (int) Constants.RegionSize)) -
299 ((conn.Y * (int) Constants.RegionSize)));
300
301 Vector3 extents = Vector3.Zero;
302 extents.Y = regionConnections.YEnd + conn.YEnd;
303 extents.X = conn.XEnd + conn.XEnd;
304
305 m_log.DebugFormat("Scene: {0} to the northwest of Scene{1}. Offset: {2}. Extents:{3}",
306 conn.RegionScene.RegionInfo.RegionName,
307 regionConnections.RegionScene.RegionInfo.RegionName,
308 offset, extents);
309
310 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
311
312 connectedYN = true;
313 break;
314 }
315 */
316
317 /*
318 //If we're one region over x +y
319 //xxx
320 //xxx
321 //xyx
322 if ((((int)conn.X * (int)Constants.RegionSize)
323 == (regionConnections.X * (int)Constants.RegionSize))
324 && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
325 == (regionConnections.Y * (int)Constants.RegionSize)))
326 {
327 Vector3 offset = Vector3.Zero;
328 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
329 ((conn.X * (int)Constants.RegionSize)));
330 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
331 ((conn.Y * (int)Constants.RegionSize)));
332
333 Vector3 extents = Vector3.Zero;
334 extents.Y = regionConnections.YEnd + conn.YEnd;
335 extents.X = conn.XEnd;
336
337 m_log.DebugFormat("Scene: {0} to the north of Scene{1}. Offset: {2}. Extents:{3}",
338 conn.RegionScene.RegionInfo.RegionName,
339 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
340
341 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
342 connectedYN = true;
343 break;
344 }
345 */
346
347 /*
348 // If we're one region over -x +y
349 //xxx
350 //xxx
351 //yxx
352 if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
353 == (regionConnections.X * (int)Constants.RegionSize))
354 && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
355 == (regionConnections.Y * (int)Constants.RegionSize)))
356 {
357 Vector3 offset = Vector3.Zero;
358 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
359 ((conn.X * (int)Constants.RegionSize)));
360 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
361 ((conn.Y * (int)Constants.RegionSize)));
362
363 Vector3 extents = Vector3.Zero;
364 extents.Y = regionConnections.YEnd + conn.YEnd;
365 extents.X = conn.XEnd + conn.XEnd;
366
367 m_log.DebugFormat("Scene: {0} to the northeast of Scene. Offset: {2}. Extents:{3}",
368 conn.RegionScene.RegionInfo.RegionName,
369 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
370
371 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
372
373
374 connectedYN = true;
375 break;
376 }
377 */
378
379 /*
380 // If we're one region over -x y
381 //xxx
382 //yxx
383 //xxx
384 if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
385 == (regionConnections.X * (int)Constants.RegionSize))
386 && (((int)conn.Y * (int)Constants.RegionSize)
387 == (regionConnections.Y * (int)Constants.RegionSize)))
388 {
389 Vector3 offset = Vector3.Zero;
390 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
391 ((conn.X * (int)Constants.RegionSize)));
392 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
393 ((conn.Y * (int)Constants.RegionSize)));
394
395 Vector3 extents = Vector3.Zero;
396 extents.Y = regionConnections.YEnd;
397 extents.X = conn.XEnd + conn.XEnd;
398
399 m_log.DebugFormat("Scene: {0} to the east of Scene{1} Offset: {2}. Extents:{3}",
400 conn.RegionScene.RegionInfo.RegionName,
401 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
402
403 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
404
405 connectedYN = true;
406 break;
407 }
408 */
409
410 /*
411 // If we're one region over -x -y
412 //yxx
413 //xxx
414 //xxx
415 if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
416 == (regionConnections.X * (int)Constants.RegionSize))
417 && (((int)conn.Y * (int)Constants.RegionSize) + conn.YEnd
418 == (regionConnections.Y * (int)Constants.RegionSize)))
419 {
420 Vector3 offset = Vector3.Zero;
421 offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
422 ((conn.X * (int)Constants.RegionSize)));
423 offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
424 ((conn.Y * (int)Constants.RegionSize)));
425
426 Vector3 extents = Vector3.Zero;
427 extents.Y = regionConnections.YEnd + conn.YEnd;
428 extents.X = conn.XEnd + conn.XEnd;
429
430 m_log.DebugFormat("Scene: {0} to the northeast of Scene{1} Offset: {2}. Extents:{3}",
431 conn.RegionScene.RegionInfo.RegionName,
432 regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
433
434 scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
435
436 connectedYN = true;
437 break;
438 }
439 */
440 #endregion
441
442
443 // Check to see if this new region is adjacent to the root region.
444 // Note that we expect the regions to be combined from the root region outward
445 // thus the requirement for the ordering in the configuration files.
446
447 // If we're one region over +x y (i.e. root region is to the west)
448 //xxx
449 //xxy
450 //xxx
451 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
452 {
453 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
454 break;
455 }
456
457 // If we're one region over x +y (i.e. root region is to the south)
458 //xyx
459 //xxx
460 //xxx
461 if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
462 {
463 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
464 break;
465 }
466
467 // If we're one region over +x +y (i.e. root region is to the south-west)
468 //xxy
469 //xxx
470 //xxx
471 if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
472 {
473 connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
474 break;
475 }
476 }
477
478 // If !connectYN means that this region is a root region
479 if (!connectedYN)
480 {
481 DoWorkForRootRegion(newConn, scene);
482 }
483 }
484 }
485
486 private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
487 {
488 // Offset (in meters) from the base of this region to the base of the root region.
489 Vector3 offset = Vector3.Zero;
490 offset.X = newConn.PosX - rootConn.PosX;
491 offset.Y = newConn.PosY - rootConn.PosY;
492
493 // The new total size of the region (in meters)
494 // We just extend the X and Y dimensions so the extent might temporarily include areas without regions.
495 Vector3 extents = Vector3.Zero;
496 extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
497 extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
498
499 rootConn.UpdateExtents(extents);
500
501 m_log.DebugFormat(
502 "[REGION COMBINER MODULE]: Root region {0} is to the west of region {1}, Offset: {2}, Extents: {3}",
503 rootConn.RegionScene.RegionInfo.RegionName,
504 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
505
506 RegionData ConnectedRegion = new RegionData();
507 ConnectedRegion.Offset = offset;
508 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
509 ConnectedRegion.RegionScene = scene;
510 rootConn.ConnectedRegions.Add(ConnectedRegion);
511
512 // Inform root region Physics about the extents of this region
513 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
514
515 // Inform Child region that it needs to forward it's terrain to the root region
516 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
517
518 // Reset Terrain.. since terrain loads before we get here, we need to load
519 // it again so it loads in the root region
520 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
521
522 // Create a client event forwarder and add this region's events to the root region.
523 if (rootConn.ClientEventForwarder != null)
524 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
525
526 return true;
527 }
528
529 /*
530 * 20140215 radams1: The border stuff was removed and the addition of regions to the mega-regions
531 * was generalized. These functions are not needed for the generalized solution but left for reference.
532 private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
533 {
534 Vector3 offset = Vector3.Zero;
535 offset.X = newConn.PosX - rootConn.PosX;
536 offset.Y = newConn.PosY - rootConn.PosY;
537
538 Vector3 extents = Vector3.Zero;
539 extents.Y = newConn.YEnd + rootConn.YEnd;
540 extents.X = rootConn.XEnd;
541 rootConn.UpdateExtents(extents);
542
543 RegionData ConnectedRegion = new RegionData();
544 ConnectedRegion.Offset = offset;
545 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
546 ConnectedRegion.RegionScene = scene;
547 rootConn.ConnectedRegions.Add(ConnectedRegion);
548
549 m_log.DebugFormat(
550 "[REGION COMBINER MODULE]: Root region {0} is to the south of region {1}, Offset: {2}, Extents: {3}",
551 rootConn.RegionScene.RegionInfo.RegionName,
552 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
553
554 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
555 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
556
557 // Reset Terrain.. since terrain normally loads first.
558 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
559 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
560 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
561
562 if (rootConn.ClientEventForwarder != null)
563 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
564
565 return true;
566 }
567
568 private bool DoWorkForOneRegionOverPlusXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
569 {
570 Vector3 offset = Vector3.Zero;
571 offset.X = newConn.PosX - rootConn.PosX;
572 offset.Y = newConn.PosY - rootConn.PosY;
573
574 Vector3 extents = Vector3.Zero;
575
576 // We do not want to inflate the extents for regions strictly to the NE of the root region, since this
577 // would double count regions strictly to the north and east that have already been added.
578// extents.Y = regionConnections.YEnd + conn.YEnd;
579// extents.X = regionConnections.XEnd + conn.XEnd;
580// conn.UpdateExtents(extents);
581
582 extents.Y = rootConn.YEnd;
583 extents.X = rootConn.XEnd;
584
585 RegionData ConnectedRegion = new RegionData();
586 ConnectedRegion.Offset = offset;
587 ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
588 ConnectedRegion.RegionScene = scene;
589
590 rootConn.ConnectedRegions.Add(ConnectedRegion);
591
592 m_log.DebugFormat(
593 "[REGION COMBINER MODULE]: Region {0} is to the southwest of Scene {1}, Offset: {2}, Extents: {3}",
594 rootConn.RegionScene.RegionInfo.RegionName,
595 newConn.RegionScene.RegionInfo.RegionName, offset, extents);
596
597 rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
598 scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
599
600 // Reset Terrain.. since terrain normally loads first.
601 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
602 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
603 //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
604
605 if (rootConn.ClientEventForwarder != null)
606 rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
607
608 return true;
609
610 //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
611 }
612 */
613
614 private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
615 {
616 m_log.DebugFormat("[REGION COMBINER MODULE]: Adding root region {0}", scene.RegionInfo.RegionName);
617
618 RegionData rdata = new RegionData();
619 rdata.Offset = Vector3.Zero;
620 rdata.RegionId = scene.RegionInfo.originRegionID;
621 rdata.RegionScene = scene;
622 // save it's land channel
623 rootConn.RegionLandChannel = scene.LandChannel;
624
625 // Substitue our landchannel
626 RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata, scene.LandChannel,
627 rootConn.ConnectedRegions);
628
629 scene.LandChannel = lnd;
630
631 // Forward the permissions modules of each of the connected regions to the root region
632 lock (m_regions)
633 {
634 foreach (RegionData r in rootConn.ConnectedRegions)
635 {
636 ForwardPermissionRequests(rootConn, r.RegionScene);
637 }
638
639 // Create the root region's Client Event Forwarder
640 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn);
641
642 // Sets up the CoarseLocationUpdate forwarder for this root region
643 scene.EventManager.OnNewPresence += SetCoarseLocationDelegate;
644
645 // Adds this root region to a dictionary of regions that are connectable
646 m_regions.Add(scene.RegionInfo.originRegionID, rootConn);
647 }
648 }
649
650 private void SetCoarseLocationDelegate(ScenePresence presence)
651 {
652 presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates);
653 }
654
655 // This delegate was refactored for non-combined regions.
656 // This combined region version will not use the pre-compiled lists of locations and ids
657 private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
658 {
659 RegionConnections connectiondata = null;
660 lock (m_regions)
661 {
662 if (m_regions.ContainsKey(sceneId))
663 connectiondata = m_regions[sceneId];
664 else
665 return;
666 }
667
668 List<Vector3> CoarseLocations = new List<Vector3>();
669 List<UUID> AvatarUUIDs = new List<UUID>();
670
671 connectiondata.RegionScene.ForEachRootScenePresence(delegate(ScenePresence sp)
672 {
673 if (sp.UUID != presence.UUID)
674 {
675 CoarseLocations.Add(sp.AbsolutePosition);
676 AvatarUUIDs.Add(sp.UUID);
677 }
678 });
679
680 DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence);
681 }
682
683 private void DistributeCoarseLocationUpdates(List<Vector3> locations, List<UUID> uuids,
684 RegionConnections connectiondata, ScenePresence rootPresence)
685 {
686 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
687 //List<IClientAPI> clients = new List<IClientAPI>();
688 Dictionary<Vector2, RegionCoarseLocationStruct> updates = new Dictionary<Vector2, RegionCoarseLocationStruct>();
689
690 // Root Region entry
691 RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct();
692 rootupdatedata.Locations = new List<Vector3>();
693 rootupdatedata.Uuids = new List<UUID>();
694 rootupdatedata.Offset = Vector2.Zero;
695
696 rootupdatedata.UserAPI = rootPresence.ControllingClient;
697
698 if (rootupdatedata.UserAPI != null)
699 updates.Add(Vector2.Zero, rootupdatedata);
700
701 //Each Region needs an entry or we will end up with dead minimap dots
702 foreach (RegionData regiondata in rdata)
703 {
704 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y);
705 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
706 updatedata.Locations = new List<Vector3>();
707 updatedata.Uuids = new List<UUID>();
708 updatedata.Offset = offset;
709
710 if (offset == Vector2.Zero)
711 updatedata.UserAPI = rootPresence.ControllingClient;
712 else
713 updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata);
714
715 if (updatedata.UserAPI != null)
716 updates.Add(offset, updatedata);
717 }
718
719 // go over the locations and assign them to an IClientAPI
720 for (int i = 0; i < locations.Count; i++)
721 //{locations[i]/(int) Constants.RegionSize;
722 {
723 Vector3 pPosition = new Vector3((int)locations[i].X / (int)Constants.RegionSize,
724 (int)locations[i].Y / (int)Constants.RegionSize, locations[i].Z);
725 Vector2 offset = new Vector2(pPosition.X*(int) Constants.RegionSize,
726 pPosition.Y*(int) Constants.RegionSize);
727
728 if (!updates.ContainsKey(offset))
729 {
730 // This shouldn't happen
731 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
732 updatedata.Locations = new List<Vector3>();
733 updatedata.Uuids = new List<UUID>();
734 updatedata.Offset = offset;
735
736 if (offset == Vector2.Zero)
737 updatedata.UserAPI = rootPresence.ControllingClient;
738 else
739 updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata);
740
741 updates.Add(offset,updatedata);
742 }
743
744 updates[offset].Locations.Add(locations[i]);
745 updates[offset].Uuids.Add(uuids[i]);
746 }
747
748 // Send out the CoarseLocationupdates from their respective client connection based on where the avatar is
749 foreach (Vector2 offset in updates.Keys)
750 {
751 if (updates[offset].UserAPI != null)
752 {
753 updates[offset].UserAPI.SendCoarseLocationUpdate(updates[offset].Uuids,updates[offset].Locations);
754 }
755 }
756 }
757
758 /// <summary>
759 /// Locates a the Client of a particular region in an Array of RegionData based on offset
760 /// </summary>
761 /// <param name="offset"></param>
762 /// <param name="uUID"></param>
763 /// <param name="rdata"></param>
764 /// <returns>IClientAPI or null</returns>
765 private IClientAPI LocateUsersChildAgentIClientAPI(Vector2 offset, UUID uUID, RegionData[] rdata)
766 {
767 IClientAPI returnclient = null;
768 foreach (RegionData r in rdata)
769 {
770 if (r.Offset.X == offset.X && r.Offset.Y == offset.Y)
771 {
772 return r.RegionScene.SceneGraph.GetControllingClient(uUID);
773 }
774 }
775
776 return returnclient;
777 }
778
779 public void PostInitialise()
780 {
781 }
782
783// /// <summary>
784// /// TODO:
785// /// </summary>
786// /// <param name="rdata"></param>
787// public void UnCombineRegion(RegionData rdata)
788// {
789// lock (m_regions)
790// {
791// if (m_regions.ContainsKey(rdata.RegionId))
792// {
793// // uncombine root region and virtual regions
794// }
795// else
796// {
797// foreach (RegionConnections r in m_regions.Values)
798// {
799// foreach (RegionData rd in r.ConnectedRegions)
800// {
801// if (rd.RegionId == rdata.RegionId)
802// {
803// // uncombine virtual region
804// }
805// }
806// }
807// }
808// }
809// }
810
811 public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
812 {
813 if (BigRegion.PermissionModule == null)
814 BigRegion.PermissionModule = new RegionCombinerPermissionModule(BigRegion.RegionScene);
815
816 VirtualRegion.Permissions.OnBypassPermissions += BigRegion.PermissionModule.BypassPermissions;
817 VirtualRegion.Permissions.OnSetBypassPermissions += BigRegion.PermissionModule.SetBypassPermissions;
818 VirtualRegion.Permissions.OnPropagatePermissions += BigRegion.PermissionModule.PropagatePermissions;
819 VirtualRegion.Permissions.OnGenerateClientFlags += BigRegion.PermissionModule.GenerateClientFlags;
820 VirtualRegion.Permissions.OnAbandonParcel += BigRegion.PermissionModule.CanAbandonParcel;
821 VirtualRegion.Permissions.OnReclaimParcel += BigRegion.PermissionModule.CanReclaimParcel;
822 VirtualRegion.Permissions.OnDeedParcel += BigRegion.PermissionModule.CanDeedParcel;
823 VirtualRegion.Permissions.OnDeedObject += BigRegion.PermissionModule.CanDeedObject;
824 VirtualRegion.Permissions.OnIsGod += BigRegion.PermissionModule.IsGod;
825 VirtualRegion.Permissions.OnDuplicateObject += BigRegion.PermissionModule.CanDuplicateObject;
826 VirtualRegion.Permissions.OnDeleteObject += BigRegion.PermissionModule.CanDeleteObject; //MAYBE FULLY IMPLEMENTED
827 VirtualRegion.Permissions.OnEditObject += BigRegion.PermissionModule.CanEditObject; //MAYBE FULLY IMPLEMENTED
828 VirtualRegion.Permissions.OnEditParcelProperties += BigRegion.PermissionModule.CanEditParcelProperties; //MAYBE FULLY IMPLEMENTED
829 VirtualRegion.Permissions.OnInstantMessage += BigRegion.PermissionModule.CanInstantMessage;
830 VirtualRegion.Permissions.OnInventoryTransfer += BigRegion.PermissionModule.CanInventoryTransfer; //NOT YET IMPLEMENTED
831 VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED
832 VirtualRegion.Permissions.OnMoveObject += BigRegion.PermissionModule.CanMoveObject; //MAYBE FULLY IMPLEMENTED
833 VirtualRegion.Permissions.OnObjectEntry += BigRegion.PermissionModule.CanObjectEntry;
834 VirtualRegion.Permissions.OnReturnObjects += BigRegion.PermissionModule.CanReturnObjects; //NOT YET IMPLEMENTED
835 VirtualRegion.Permissions.OnRezObject += BigRegion.PermissionModule.CanRezObject; //MAYBE FULLY IMPLEMENTED
836 VirtualRegion.Permissions.OnRunConsoleCommand += BigRegion.PermissionModule.CanRunConsoleCommand;
837 VirtualRegion.Permissions.OnRunScript += BigRegion.PermissionModule.CanRunScript; //NOT YET IMPLEMENTED
838 VirtualRegion.Permissions.OnCompileScript += BigRegion.PermissionModule.CanCompileScript;
839 VirtualRegion.Permissions.OnSellParcel += BigRegion.PermissionModule.CanSellParcel;
840 VirtualRegion.Permissions.OnTakeObject += BigRegion.PermissionModule.CanTakeObject;
841 VirtualRegion.Permissions.OnTakeCopyObject += BigRegion.PermissionModule.CanTakeCopyObject;
842 VirtualRegion.Permissions.OnTerraformLand += BigRegion.PermissionModule.CanTerraformLand;
843 VirtualRegion.Permissions.OnLinkObject += BigRegion.PermissionModule.CanLinkObject; //NOT YET IMPLEMENTED
844 VirtualRegion.Permissions.OnDelinkObject += BigRegion.PermissionModule.CanDelinkObject; //NOT YET IMPLEMENTED
845 VirtualRegion.Permissions.OnBuyLand += BigRegion.PermissionModule.CanBuyLand; //NOT YET IMPLEMENTED
846 VirtualRegion.Permissions.OnViewNotecard += BigRegion.PermissionModule.CanViewNotecard; //NOT YET IMPLEMENTED
847 VirtualRegion.Permissions.OnViewScript += BigRegion.PermissionModule.CanViewScript; //NOT YET IMPLEMENTED
848 VirtualRegion.Permissions.OnEditNotecard += BigRegion.PermissionModule.CanEditNotecard; //NOT YET IMPLEMENTED
849 VirtualRegion.Permissions.OnEditScript += BigRegion.PermissionModule.CanEditScript; //NOT YET IMPLEMENTED
850 VirtualRegion.Permissions.OnCreateObjectInventory += BigRegion.PermissionModule.CanCreateObjectInventory; //NOT IMPLEMENTED HERE
851 VirtualRegion.Permissions.OnEditObjectInventory += BigRegion.PermissionModule.CanEditObjectInventory;//MAYBE FULLY IMPLEMENTED
852 VirtualRegion.Permissions.OnCopyObjectInventory += BigRegion.PermissionModule.CanCopyObjectInventory; //NOT YET IMPLEMENTED
853 VirtualRegion.Permissions.OnDeleteObjectInventory += BigRegion.PermissionModule.CanDeleteObjectInventory; //NOT YET IMPLEMENTED
854 VirtualRegion.Permissions.OnResetScript += BigRegion.PermissionModule.CanResetScript;
855 VirtualRegion.Permissions.OnCreateUserInventory += BigRegion.PermissionModule.CanCreateUserInventory; //NOT YET IMPLEMENTED
856 VirtualRegion.Permissions.OnCopyUserInventory += BigRegion.PermissionModule.CanCopyUserInventory; //NOT YET IMPLEMENTED
857 VirtualRegion.Permissions.OnEditUserInventory += BigRegion.PermissionModule.CanEditUserInventory; //NOT YET IMPLEMENTED
858 VirtualRegion.Permissions.OnDeleteUserInventory += BigRegion.PermissionModule.CanDeleteUserInventory; //NOT YET IMPLEMENTED
859 VirtualRegion.Permissions.OnTeleport += BigRegion.PermissionModule.CanTeleport; //NOT YET IMPLEMENTED
860 }
861
862 #region console commands
863
864 public void FixPhantoms(string module, string[] cmdparams)
865 {
866 List<Scene> scenes = new List<Scene>(m_startingScenes.Values);
867
868 foreach (Scene s in scenes)
869 {
870 MainConsole.Instance.OutputFormat("Fixing phantoms for {0}", s.RegionInfo.RegionName);
871
872 s.ForEachSOG(so => so.AbsolutePosition = so.AbsolutePosition);
873 }
874 }
875
876 #endregion
877 }
878}