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