aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
diff options
context:
space:
mode:
authorRobert Adams2015-09-08 04:54:16 -0700
committerRobert Adams2015-09-08 04:54:16 -0700
commite5367d822be9b05e74c859afe2d2956a3e95aa33 (patch)
treee904050a30715df587aa527d7f313755177726a7 /OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
parentadd lost admin_reset_land method (diff)
parentDeleted access control spec from [LoginService] section of standalone config.... (diff)
downloadopensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.zip
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.gz
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.bz2
opensim-SC_OLD-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.xz
Merge of ubitworkvarnew with opensim/master as of 20150905.
This integrates the OpenSim refactoring to make physics, etc into modules. AVN physics hasn't been moved to new location. Does not compile yet. Merge branch 'osmaster' into mbworknew1
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}