From f9a7099abcc8bb2da81dc514adbe7803b14fcd6f Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Fri, 4 Sep 2015 15:12:36 -0700
Subject: Moved RegionCombinerModule to OptionalModules. Removed it as its own
top-level project/dll.
---
.../RegionCombinerModule/RegionCombinerModule.cs | 878 +++++++++++++++++++++
1 file changed, 878 insertions(+)
create mode 100644 OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs
(limited to 'OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerModule.cs')
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 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using log4net;
+using Nini.Config;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Framework.Client;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Framework.Console;
+using OpenSim.Region.PhysicsModules.SharedBase;
+using Mono.Addins;
+
+namespace OpenSim.Region.RegionCombinerModule
+{
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionCombinerModule")]
+ public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+// private static string LogHeader = "[REGION COMBINER MODULE]";
+
+ public string Name
+ {
+ get { return "RegionCombinerModule"; }
+ }
+
+ public Type ReplaceableInterface
+ {
+ get { return null; }
+ }
+
+ ///
+ /// Is this module enabled?
+ ///
+ private bool m_combineContiguousRegions = false;
+
+ ///
+ /// This holds the root regions for the megaregions.
+ ///
+ ///
+ /// Usually there is only ever one megaregion (and hence only one entry here).
+ ///
+ private Dictionary m_regions = new Dictionary();
+
+ ///
+ /// The scenes that comprise the megaregion.
+ ///
+ private Dictionary m_startingScenes = new Dictionary();
+
+ public void Initialise(IConfigSource source)
+ {
+ IConfig myConfig = source.Configs["Startup"];
+ m_combineContiguousRegions = myConfig.GetBoolean("CombineContiguousRegions", false);
+
+ MainConsole.Instance.Commands.AddCommand(
+ "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms",
+ "Fixes phantom objects after an import to a megaregion or a change from a megaregion back to normal regions",
+ FixPhantoms);
+ }
+
+ public void Close()
+ {
+ }
+
+ public void AddRegion(Scene scene)
+ {
+ if (m_combineContiguousRegions)
+ scene.RegisterModuleInterface(this);
+ }
+
+ public void RemoveRegion(Scene scene)
+ {
+ lock (m_startingScenes)
+ m_startingScenes.Remove(scene.RegionInfo.originRegionID);
+ }
+
+ public void RegionLoaded(Scene scene)
+ {
+ lock (m_startingScenes)
+ m_startingScenes.Add(scene.RegionInfo.originRegionID, scene);
+
+ if (m_combineContiguousRegions)
+ {
+ RegionLoadedDoWork(scene);
+
+ scene.EventManager.OnNewPresence += NewPresence;
+ }
+ }
+
+ public bool IsRootForMegaregion(UUID regionId)
+ {
+ lock (m_regions)
+ return m_regions.ContainsKey(regionId);
+ }
+
+ public Vector2 GetSizeOfMegaregion(UUID regionId)
+ {
+ lock (m_regions)
+ {
+ if (m_regions.ContainsKey(regionId))
+ {
+ RegionConnections rootConn = m_regions[regionId];
+
+ return new Vector2((float)rootConn.XEnd, (float)rootConn.YEnd);
+ }
+ }
+
+ throw new Exception(string.Format("Region with id {0} not found", regionId));
+ }
+
+ // Test to see if this postiion (relative to the region) is within the area covered
+ // by this megaregion.
+ public bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy)
+ {
+ bool ret = false;
+ if (xx < 0 || yy < 0)
+ return ret;
+
+ foreach (RegionConnections rootRegion in m_regions.Values)
+ {
+ if (currentRegion == rootRegion.RegionId)
+ {
+ // The caller is in the root region so this is an easy test
+ if (xx < rootRegion.XEnd && yy < rootRegion.YEnd)
+ {
+ ret = true;
+ }
+ break;
+ }
+ else
+ {
+ // Maybe the caller is in one of the sub-regions
+ foreach (RegionData childRegion in rootRegion.ConnectedRegions)
+ {
+ if (currentRegion == childRegion.RegionId)
+ {
+ // This is a child. Diddle the offsets and check if in
+ Vector3 positionInMegaregion = childRegion.Offset;
+ positionInMegaregion.X += xx;
+ positionInMegaregion.Y += yy;
+ if (positionInMegaregion.X < rootRegion.XEnd && positionInMegaregion.Y < rootRegion.YEnd)
+ {
+ ret = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ private void NewPresence(ScenePresence presence)
+ {
+ if (presence.IsChildAgent)
+ {
+ byte[] throttleData;
+
+ try
+ {
+ throttleData = presence.ControllingClient.GetThrottlesPacked(1);
+ }
+ catch (NotImplementedException)
+ {
+ return;
+ }
+
+ if (throttleData == null)
+ return;
+
+ if (throttleData.Length == 0)
+ return;
+
+ if (throttleData.Length != 28)
+ return;
+
+ byte[] adjData;
+ int pos = 0;
+
+ if (!BitConverter.IsLittleEndian)
+ {
+ byte[] newData = new byte[7 * 4];
+ Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
+
+ for (int i = 0; i < 7; i++)
+ Array.Reverse(newData, i * 4, 4);
+
+ adjData = newData;
+ }
+ else
+ {
+ adjData = throttleData;
+ }
+
+ // 0.125f converts from bits to bytes
+ int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
+ int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
+ int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
+ int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
+ int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
+ int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
+ int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
+ // State is a subcategory of task that we allocate a percentage to
+
+
+ //int total = resend + land + wind + cloud + task + texture + asset;
+
+ byte[] data = new byte[7 * 4];
+ int ii = 0;
+
+ Buffer.BlockCopy(Utils.FloatToBytes(resend), 0, data, ii, 4); ii += 4;
+ Buffer.BlockCopy(Utils.FloatToBytes(land * 50), 0, data, ii, 4); ii += 4;
+ Buffer.BlockCopy(Utils.FloatToBytes(wind), 0, data, ii, 4); ii += 4;
+ Buffer.BlockCopy(Utils.FloatToBytes(cloud), 0, data, ii, 4); ii += 4;
+ Buffer.BlockCopy(Utils.FloatToBytes(task), 0, data, ii, 4); ii += 4;
+ Buffer.BlockCopy(Utils.FloatToBytes(texture), 0, data, ii, 4); ii += 4;
+ Buffer.BlockCopy(Utils.FloatToBytes(asset), 0, data, ii, 4);
+
+ try
+ {
+ presence.ControllingClient.SetChildAgentThrottle(data);
+ }
+ catch (NotImplementedException)
+ {
+ return;
+ }
+ }
+ }
+
+ private void RegionLoadedDoWork(Scene scene)
+ {
+/*
+ // For testing on a single instance
+ if (scene.RegionInfo.RegionLocX == 1004 && scene.RegionInfo.RegionLocY == 1000)
+ return;
+ //
+*/
+
+ RegionConnections newConn = new RegionConnections();
+ newConn.ConnectedRegions = new List();
+ newConn.RegionScene = scene;
+ newConn.RegionLandChannel = scene.LandChannel;
+ newConn.RegionId = scene.RegionInfo.originRegionID;
+ newConn.X = scene.RegionInfo.RegionLocX;
+ newConn.Y = scene.RegionInfo.RegionLocY;
+ newConn.XEnd = scene.RegionInfo.RegionSizeX;
+ newConn.YEnd = scene.RegionInfo.RegionSizeX;
+
+ lock (m_regions)
+ {
+ bool connectedYN = false;
+
+ foreach (RegionConnections rootConn in m_regions.Values)
+ {
+ #region commented
+ /*
+ // If we're one region over +x +y
+ //xxy
+ //xxx
+ //xxx
+ if ((((int)conn.X * (int)Constants.RegionSize) + conn.XEnd
+ == (regionConnections.X * (int)Constants.RegionSize))
+ && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
+ == (regionConnections.Y * (int)Constants.RegionSize)))
+ {
+ Vector3 offset = Vector3.Zero;
+ offset.X = (((regionConnections.X * (int) Constants.RegionSize)) -
+ ((conn.X * (int) Constants.RegionSize)));
+ offset.Y = (((regionConnections.Y * (int) Constants.RegionSize)) -
+ ((conn.Y * (int) Constants.RegionSize)));
+
+ Vector3 extents = Vector3.Zero;
+ extents.Y = regionConnections.YEnd + conn.YEnd;
+ extents.X = conn.XEnd + conn.XEnd;
+
+ m_log.DebugFormat("Scene: {0} to the northwest of Scene{1}. Offset: {2}. Extents:{3}",
+ conn.RegionScene.RegionInfo.RegionName,
+ regionConnections.RegionScene.RegionInfo.RegionName,
+ offset, extents);
+
+ scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
+
+ connectedYN = true;
+ break;
+ }
+ */
+
+ /*
+ //If we're one region over x +y
+ //xxx
+ //xxx
+ //xyx
+ if ((((int)conn.X * (int)Constants.RegionSize)
+ == (regionConnections.X * (int)Constants.RegionSize))
+ && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
+ == (regionConnections.Y * (int)Constants.RegionSize)))
+ {
+ Vector3 offset = Vector3.Zero;
+ offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
+ ((conn.X * (int)Constants.RegionSize)));
+ offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
+ ((conn.Y * (int)Constants.RegionSize)));
+
+ Vector3 extents = Vector3.Zero;
+ extents.Y = regionConnections.YEnd + conn.YEnd;
+ extents.X = conn.XEnd;
+
+ m_log.DebugFormat("Scene: {0} to the north of Scene{1}. Offset: {2}. Extents:{3}",
+ conn.RegionScene.RegionInfo.RegionName,
+ regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
+
+ scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
+ connectedYN = true;
+ break;
+ }
+ */
+
+ /*
+ // If we're one region over -x +y
+ //xxx
+ //xxx
+ //yxx
+ if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
+ == (regionConnections.X * (int)Constants.RegionSize))
+ && (((int)conn.Y * (int)Constants.RegionSize) - conn.YEnd
+ == (regionConnections.Y * (int)Constants.RegionSize)))
+ {
+ Vector3 offset = Vector3.Zero;
+ offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
+ ((conn.X * (int)Constants.RegionSize)));
+ offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
+ ((conn.Y * (int)Constants.RegionSize)));
+
+ Vector3 extents = Vector3.Zero;
+ extents.Y = regionConnections.YEnd + conn.YEnd;
+ extents.X = conn.XEnd + conn.XEnd;
+
+ m_log.DebugFormat("Scene: {0} to the northeast of Scene. Offset: {2}. Extents:{3}",
+ conn.RegionScene.RegionInfo.RegionName,
+ regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
+
+ scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
+
+
+ connectedYN = true;
+ break;
+ }
+ */
+
+ /*
+ // If we're one region over -x y
+ //xxx
+ //yxx
+ //xxx
+ if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
+ == (regionConnections.X * (int)Constants.RegionSize))
+ && (((int)conn.Y * (int)Constants.RegionSize)
+ == (regionConnections.Y * (int)Constants.RegionSize)))
+ {
+ Vector3 offset = Vector3.Zero;
+ offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
+ ((conn.X * (int)Constants.RegionSize)));
+ offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
+ ((conn.Y * (int)Constants.RegionSize)));
+
+ Vector3 extents = Vector3.Zero;
+ extents.Y = regionConnections.YEnd;
+ extents.X = conn.XEnd + conn.XEnd;
+
+ m_log.DebugFormat("Scene: {0} to the east of Scene{1} Offset: {2}. Extents:{3}",
+ conn.RegionScene.RegionInfo.RegionName,
+ regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
+
+ scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
+
+ connectedYN = true;
+ break;
+ }
+ */
+
+ /*
+ // If we're one region over -x -y
+ //yxx
+ //xxx
+ //xxx
+ if ((((int)conn.X * (int)Constants.RegionSize) - conn.XEnd
+ == (regionConnections.X * (int)Constants.RegionSize))
+ && (((int)conn.Y * (int)Constants.RegionSize) + conn.YEnd
+ == (regionConnections.Y * (int)Constants.RegionSize)))
+ {
+ Vector3 offset = Vector3.Zero;
+ offset.X = (((regionConnections.X * (int)Constants.RegionSize)) -
+ ((conn.X * (int)Constants.RegionSize)));
+ offset.Y = (((regionConnections.Y * (int)Constants.RegionSize)) -
+ ((conn.Y * (int)Constants.RegionSize)));
+
+ Vector3 extents = Vector3.Zero;
+ extents.Y = regionConnections.YEnd + conn.YEnd;
+ extents.X = conn.XEnd + conn.XEnd;
+
+ m_log.DebugFormat("Scene: {0} to the northeast of Scene{1} Offset: {2}. Extents:{3}",
+ conn.RegionScene.RegionInfo.RegionName,
+ regionConnections.RegionScene.RegionInfo.RegionName, offset, extents);
+
+ scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset, extents);
+
+ connectedYN = true;
+ break;
+ }
+ */
+ #endregion
+
+
+ // Check to see if this new region is adjacent to the root region.
+ // Note that we expect the regions to be combined from the root region outward
+ // thus the requirement for the ordering in the configuration files.
+
+ // If we're one region over +x y (i.e. root region is to the west)
+ //xxx
+ //xxy
+ //xxx
+ if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
+ {
+ connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
+ break;
+ }
+
+ // If we're one region over x +y (i.e. root region is to the south)
+ //xyx
+ //xxx
+ //xxx
+ if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
+ {
+ connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
+ break;
+ }
+
+ // If we're one region over +x +y (i.e. root region is to the south-west)
+ //xxy
+ //xxx
+ //xxx
+ if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
+ {
+ connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
+ break;
+ }
+ }
+
+ // If !connectYN means that this region is a root region
+ if (!connectedYN)
+ {
+ DoWorkForRootRegion(newConn, scene);
+ }
+ }
+ }
+
+ private bool DoWorkForOneRegionOverPlusXY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
+ {
+ // Offset (in meters) from the base of this region to the base of the root region.
+ Vector3 offset = Vector3.Zero;
+ offset.X = newConn.PosX - rootConn.PosX;
+ offset.Y = newConn.PosY - rootConn.PosY;
+
+ // The new total size of the region (in meters)
+ // We just extend the X and Y dimensions so the extent might temporarily include areas without regions.
+ Vector3 extents = Vector3.Zero;
+ extents.X = Math.Max(rootConn.XEnd, offset.X + newConn.RegionScene.RegionInfo.RegionSizeX);
+ extents.Y = Math.Max(rootConn.YEnd, offset.Y + newConn.RegionScene.RegionInfo.RegionSizeY);
+
+ rootConn.UpdateExtents(extents);
+
+ m_log.DebugFormat(
+ "[REGION COMBINER MODULE]: Root region {0} is to the west of region {1}, Offset: {2}, Extents: {3}",
+ rootConn.RegionScene.RegionInfo.RegionName,
+ newConn.RegionScene.RegionInfo.RegionName, offset, extents);
+
+ RegionData ConnectedRegion = new RegionData();
+ ConnectedRegion.Offset = offset;
+ ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
+ ConnectedRegion.RegionScene = scene;
+ rootConn.ConnectedRegions.Add(ConnectedRegion);
+
+ // Inform root region Physics about the extents of this region
+ rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
+
+ // Inform Child region that it needs to forward it's terrain to the root region
+ scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
+
+ // Reset Terrain.. since terrain loads before we get here, we need to load
+ // it again so it loads in the root region
+ scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
+
+ // Create a client event forwarder and add this region's events to the root region.
+ if (rootConn.ClientEventForwarder != null)
+ rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
+
+ return true;
+ }
+
+ /*
+ * 20140215 radams1: The border stuff was removed and the addition of regions to the mega-regions
+ * was generalized. These functions are not needed for the generalized solution but left for reference.
+ private bool DoWorkForOneRegionOverXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
+ {
+ Vector3 offset = Vector3.Zero;
+ offset.X = newConn.PosX - rootConn.PosX;
+ offset.Y = newConn.PosY - rootConn.PosY;
+
+ Vector3 extents = Vector3.Zero;
+ extents.Y = newConn.YEnd + rootConn.YEnd;
+ extents.X = rootConn.XEnd;
+ rootConn.UpdateExtents(extents);
+
+ RegionData ConnectedRegion = new RegionData();
+ ConnectedRegion.Offset = offset;
+ ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
+ ConnectedRegion.RegionScene = scene;
+ rootConn.ConnectedRegions.Add(ConnectedRegion);
+
+ m_log.DebugFormat(
+ "[REGION COMBINER MODULE]: Root region {0} is to the south of region {1}, Offset: {2}, Extents: {3}",
+ rootConn.RegionScene.RegionInfo.RegionName,
+ newConn.RegionScene.RegionInfo.RegionName, offset, extents);
+
+ rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
+ scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
+
+ // Reset Terrain.. since terrain normally loads first.
+ //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
+ scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
+ //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
+
+ if (rootConn.ClientEventForwarder != null)
+ rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
+
+ return true;
+ }
+
+ private bool DoWorkForOneRegionOverPlusXPlusY(RegionConnections rootConn, RegionConnections newConn, Scene scene)
+ {
+ Vector3 offset = Vector3.Zero;
+ offset.X = newConn.PosX - rootConn.PosX;
+ offset.Y = newConn.PosY - rootConn.PosY;
+
+ Vector3 extents = Vector3.Zero;
+
+ // We do not want to inflate the extents for regions strictly to the NE of the root region, since this
+ // would double count regions strictly to the north and east that have already been added.
+// extents.Y = regionConnections.YEnd + conn.YEnd;
+// extents.X = regionConnections.XEnd + conn.XEnd;
+// conn.UpdateExtents(extents);
+
+ extents.Y = rootConn.YEnd;
+ extents.X = rootConn.XEnd;
+
+ RegionData ConnectedRegion = new RegionData();
+ ConnectedRegion.Offset = offset;
+ ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
+ ConnectedRegion.RegionScene = scene;
+
+ rootConn.ConnectedRegions.Add(ConnectedRegion);
+
+ m_log.DebugFormat(
+ "[REGION COMBINER MODULE]: Region {0} is to the southwest of Scene {1}, Offset: {2}, Extents: {3}",
+ rootConn.RegionScene.RegionInfo.RegionName,
+ newConn.RegionScene.RegionInfo.RegionName, offset, extents);
+
+ rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
+ scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
+
+ // Reset Terrain.. since terrain normally loads first.
+ //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
+ scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
+ //conn.RegionScene.PhysicsScene.SetTerrain(conn.RegionScene.Heightmap.GetFloatsSerialised());
+
+ if (rootConn.ClientEventForwarder != null)
+ rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
+
+ return true;
+
+ //scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
+ }
+ */
+
+ private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
+ {
+ m_log.DebugFormat("[REGION COMBINER MODULE]: Adding root region {0}", scene.RegionInfo.RegionName);
+
+ RegionData rdata = new RegionData();
+ rdata.Offset = Vector3.Zero;
+ rdata.RegionId = scene.RegionInfo.originRegionID;
+ rdata.RegionScene = scene;
+ // save it's land channel
+ rootConn.RegionLandChannel = scene.LandChannel;
+
+ // Substitue our landchannel
+ RegionCombinerLargeLandChannel lnd = new RegionCombinerLargeLandChannel(rdata, scene.LandChannel,
+ rootConn.ConnectedRegions);
+
+ scene.LandChannel = lnd;
+
+ // Forward the permissions modules of each of the connected regions to the root region
+ lock (m_regions)
+ {
+ foreach (RegionData r in rootConn.ConnectedRegions)
+ {
+ ForwardPermissionRequests(rootConn, r.RegionScene);
+ }
+
+ // Create the root region's Client Event Forwarder
+ rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn);
+
+ // Sets up the CoarseLocationUpdate forwarder for this root region
+ scene.EventManager.OnNewPresence += SetCoarseLocationDelegate;
+
+ // Adds this root region to a dictionary of regions that are connectable
+ m_regions.Add(scene.RegionInfo.originRegionID, rootConn);
+ }
+ }
+
+ private void SetCoarseLocationDelegate(ScenePresence presence)
+ {
+ presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates);
+ }
+
+ // This delegate was refactored for non-combined regions.
+ // This combined region version will not use the pre-compiled lists of locations and ids
+ private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs)
+ {
+ RegionConnections connectiondata = null;
+ lock (m_regions)
+ {
+ if (m_regions.ContainsKey(sceneId))
+ connectiondata = m_regions[sceneId];
+ else
+ return;
+ }
+
+ List CoarseLocations = new List();
+ List AvatarUUIDs = new List();
+
+ connectiondata.RegionScene.ForEachRootScenePresence(delegate(ScenePresence sp)
+ {
+ if (sp.UUID != presence.UUID)
+ {
+ CoarseLocations.Add(sp.AbsolutePosition);
+ AvatarUUIDs.Add(sp.UUID);
+ }
+ });
+
+ DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence);
+ }
+
+ private void DistributeCoarseLocationUpdates(List locations, List uuids,
+ RegionConnections connectiondata, ScenePresence rootPresence)
+ {
+ RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
+ //List clients = new List();
+ Dictionary updates = new Dictionary();
+
+ // Root Region entry
+ RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct();
+ rootupdatedata.Locations = new List();
+ rootupdatedata.Uuids = new List();
+ rootupdatedata.Offset = Vector2.Zero;
+
+ rootupdatedata.UserAPI = rootPresence.ControllingClient;
+
+ if (rootupdatedata.UserAPI != null)
+ updates.Add(Vector2.Zero, rootupdatedata);
+
+ //Each Region needs an entry or we will end up with dead minimap dots
+ foreach (RegionData regiondata in rdata)
+ {
+ Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y);
+ RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
+ updatedata.Locations = new List();
+ updatedata.Uuids = new List();
+ updatedata.Offset = offset;
+
+ if (offset == Vector2.Zero)
+ updatedata.UserAPI = rootPresence.ControllingClient;
+ else
+ updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata);
+
+ if (updatedata.UserAPI != null)
+ updates.Add(offset, updatedata);
+ }
+
+ // go over the locations and assign them to an IClientAPI
+ for (int i = 0; i < locations.Count; i++)
+ //{locations[i]/(int) Constants.RegionSize;
+ {
+ Vector3 pPosition = new Vector3((int)locations[i].X / (int)Constants.RegionSize,
+ (int)locations[i].Y / (int)Constants.RegionSize, locations[i].Z);
+ Vector2 offset = new Vector2(pPosition.X*(int) Constants.RegionSize,
+ pPosition.Y*(int) Constants.RegionSize);
+
+ if (!updates.ContainsKey(offset))
+ {
+ // This shouldn't happen
+ RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
+ updatedata.Locations = new List();
+ updatedata.Uuids = new List();
+ updatedata.Offset = offset;
+
+ if (offset == Vector2.Zero)
+ updatedata.UserAPI = rootPresence.ControllingClient;
+ else
+ updatedata.UserAPI = LocateUsersChildAgentIClientAPI(offset, rootPresence.UUID, rdata);
+
+ updates.Add(offset,updatedata);
+ }
+
+ updates[offset].Locations.Add(locations[i]);
+ updates[offset].Uuids.Add(uuids[i]);
+ }
+
+ // Send out the CoarseLocationupdates from their respective client connection based on where the avatar is
+ foreach (Vector2 offset in updates.Keys)
+ {
+ if (updates[offset].UserAPI != null)
+ {
+ updates[offset].UserAPI.SendCoarseLocationUpdate(updates[offset].Uuids,updates[offset].Locations);
+ }
+ }
+ }
+
+ ///
+ /// Locates a the Client of a particular region in an Array of RegionData based on offset
+ ///
+ ///
+ ///
+ ///
+ /// IClientAPI or null
+ private IClientAPI LocateUsersChildAgentIClientAPI(Vector2 offset, UUID uUID, RegionData[] rdata)
+ {
+ IClientAPI returnclient = null;
+ foreach (RegionData r in rdata)
+ {
+ if (r.Offset.X == offset.X && r.Offset.Y == offset.Y)
+ {
+ return r.RegionScene.SceneGraph.GetControllingClient(uUID);
+ }
+ }
+
+ return returnclient;
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+// ///
+// /// TODO:
+// ///
+// ///
+// public void UnCombineRegion(RegionData rdata)
+// {
+// lock (m_regions)
+// {
+// if (m_regions.ContainsKey(rdata.RegionId))
+// {
+// // uncombine root region and virtual regions
+// }
+// else
+// {
+// foreach (RegionConnections r in m_regions.Values)
+// {
+// foreach (RegionData rd in r.ConnectedRegions)
+// {
+// if (rd.RegionId == rdata.RegionId)
+// {
+// // uncombine virtual region
+// }
+// }
+// }
+// }
+// }
+// }
+
+ public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
+ {
+ if (BigRegion.PermissionModule == null)
+ BigRegion.PermissionModule = new RegionCombinerPermissionModule(BigRegion.RegionScene);
+
+ VirtualRegion.Permissions.OnBypassPermissions += BigRegion.PermissionModule.BypassPermissions;
+ VirtualRegion.Permissions.OnSetBypassPermissions += BigRegion.PermissionModule.SetBypassPermissions;
+ VirtualRegion.Permissions.OnPropagatePermissions += BigRegion.PermissionModule.PropagatePermissions;
+ VirtualRegion.Permissions.OnGenerateClientFlags += BigRegion.PermissionModule.GenerateClientFlags;
+ VirtualRegion.Permissions.OnAbandonParcel += BigRegion.PermissionModule.CanAbandonParcel;
+ VirtualRegion.Permissions.OnReclaimParcel += BigRegion.PermissionModule.CanReclaimParcel;
+ VirtualRegion.Permissions.OnDeedParcel += BigRegion.PermissionModule.CanDeedParcel;
+ VirtualRegion.Permissions.OnDeedObject += BigRegion.PermissionModule.CanDeedObject;
+ VirtualRegion.Permissions.OnIsGod += BigRegion.PermissionModule.IsGod;
+ VirtualRegion.Permissions.OnDuplicateObject += BigRegion.PermissionModule.CanDuplicateObject;
+ VirtualRegion.Permissions.OnDeleteObject += BigRegion.PermissionModule.CanDeleteObject; //MAYBE FULLY IMPLEMENTED
+ VirtualRegion.Permissions.OnEditObject += BigRegion.PermissionModule.CanEditObject; //MAYBE FULLY IMPLEMENTED
+ VirtualRegion.Permissions.OnEditParcelProperties += BigRegion.PermissionModule.CanEditParcelProperties; //MAYBE FULLY IMPLEMENTED
+ VirtualRegion.Permissions.OnInstantMessage += BigRegion.PermissionModule.CanInstantMessage;
+ VirtualRegion.Permissions.OnInventoryTransfer += BigRegion.PermissionModule.CanInventoryTransfer; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED
+ VirtualRegion.Permissions.OnMoveObject += BigRegion.PermissionModule.CanMoveObject; //MAYBE FULLY IMPLEMENTED
+ VirtualRegion.Permissions.OnObjectEntry += BigRegion.PermissionModule.CanObjectEntry;
+ VirtualRegion.Permissions.OnReturnObjects += BigRegion.PermissionModule.CanReturnObjects; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnRezObject += BigRegion.PermissionModule.CanRezObject; //MAYBE FULLY IMPLEMENTED
+ VirtualRegion.Permissions.OnRunConsoleCommand += BigRegion.PermissionModule.CanRunConsoleCommand;
+ VirtualRegion.Permissions.OnRunScript += BigRegion.PermissionModule.CanRunScript; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnCompileScript += BigRegion.PermissionModule.CanCompileScript;
+ VirtualRegion.Permissions.OnSellParcel += BigRegion.PermissionModule.CanSellParcel;
+ VirtualRegion.Permissions.OnTakeObject += BigRegion.PermissionModule.CanTakeObject;
+ VirtualRegion.Permissions.OnTakeCopyObject += BigRegion.PermissionModule.CanTakeCopyObject;
+ VirtualRegion.Permissions.OnTerraformLand += BigRegion.PermissionModule.CanTerraformLand;
+ VirtualRegion.Permissions.OnLinkObject += BigRegion.PermissionModule.CanLinkObject; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnDelinkObject += BigRegion.PermissionModule.CanDelinkObject; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnBuyLand += BigRegion.PermissionModule.CanBuyLand; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnViewNotecard += BigRegion.PermissionModule.CanViewNotecard; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnViewScript += BigRegion.PermissionModule.CanViewScript; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnEditNotecard += BigRegion.PermissionModule.CanEditNotecard; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnEditScript += BigRegion.PermissionModule.CanEditScript; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnCreateObjectInventory += BigRegion.PermissionModule.CanCreateObjectInventory; //NOT IMPLEMENTED HERE
+ VirtualRegion.Permissions.OnEditObjectInventory += BigRegion.PermissionModule.CanEditObjectInventory;//MAYBE FULLY IMPLEMENTED
+ VirtualRegion.Permissions.OnCopyObjectInventory += BigRegion.PermissionModule.CanCopyObjectInventory; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnDeleteObjectInventory += BigRegion.PermissionModule.CanDeleteObjectInventory; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnResetScript += BigRegion.PermissionModule.CanResetScript;
+ VirtualRegion.Permissions.OnCreateUserInventory += BigRegion.PermissionModule.CanCreateUserInventory; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnCopyUserInventory += BigRegion.PermissionModule.CanCopyUserInventory; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnEditUserInventory += BigRegion.PermissionModule.CanEditUserInventory; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnDeleteUserInventory += BigRegion.PermissionModule.CanDeleteUserInventory; //NOT YET IMPLEMENTED
+ VirtualRegion.Permissions.OnTeleport += BigRegion.PermissionModule.CanTeleport; //NOT YET IMPLEMENTED
+ }
+
+ #region console commands
+
+ public void FixPhantoms(string module, string[] cmdparams)
+ {
+ List scenes = new List(m_startingScenes.Values);
+
+ foreach (Scene s in scenes)
+ {
+ MainConsole.Instance.OutputFormat("Fixing phantoms for {0}", s.RegionInfo.RegionName);
+
+ s.ForEachSOG(so => so.AbsolutePosition = so.AbsolutePosition);
+ }
+ }
+
+ #endregion
+ }
+}
--
cgit v1.1