diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index e71e81c804..2e128a708a 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -1157,7 +1157,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// Set home position
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
- (int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
+ (int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
if (null == home)
{
m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", firstName, lastName);
@@ -1387,7 +1387,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
if ((null != regionXLocation) && (null != regionYLocation))
{
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
- (int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
+ (int)Util.RegionToWorldLoc((uint)regionXLocation), (int)Util.RegionToWorldLoc((uint)regionYLocation));
if (null == home) {
m_log.WarnFormat("[RADMIN]: Unable to set home region for updated user account {0} {1}", firstName, lastName);
} else {
@@ -3118,7 +3118,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// Set home position
GridRegion home = scene.GridService.GetRegionByPosition(scopeID,
- (int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize));
+ (int)Util.RegionToWorldLoc(regionXLocation), (int)Util.RegionToWorldLoc(regionYLocation));
if (null == home) {
m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", names[0], names[1]);
} else {
diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs
index 463c621859..ca9b32716c 100644
--- a/OpenSim/Data/IRegionData.cs
+++ b/OpenSim/Data/IRegionData.cs
@@ -52,14 +52,14 @@ namespace OpenSim.Data
public int sizeY;
///
- /// Return the x-coordinate of this region.
+ /// Return the x-coordinate of this region in region units.
///
- public int coordX { get { return posX / (int)Constants.RegionSize; } }
+ public int coordX { get { return (int)Util.WorldToRegionLoc((uint)posX); } }
///
- /// Return the y-coordinate of this region.
+ /// Return the y-coordinate of this region in region units.
///
- public int coordY { get { return posY / (int)Constants.RegionSize; } }
+ public int coordY { get { return (int)Util.WorldToRegionLoc((uint)posY); } }
public Dictionary Data;
}
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index 0d09be6361..145b9c0aad 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -530,43 +530,52 @@ ELSE
///
public double[,] LoadTerrain(UUID regionID)
{
- double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terrain.Initialize();
+ double[,] ret = null;
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ if (terrData != null)
+ ret = terrData.GetDoubles();
+ return ret;
+ }
+
+ // Returns 'null' if region not found
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc";
using (SqlConnection conn = new SqlConnection(m_connectionString))
- using (SqlCommand cmd = new SqlCommand(sql, conn))
{
- // MySqlParameter param = new MySqlParameter();
- cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
- conn.Open();
- using (SqlDataReader reader = cmd.ExecuteReader())
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
{
- int rev;
- if (reader.Read())
+ // MySqlParameter param = new MySqlParameter();
+ cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
+ conn.Open();
+ using (SqlDataReader reader = cmd.ExecuteReader())
{
- MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
- BinaryReader br = new BinaryReader(str);
- for (int x = 0; x < (int)Constants.RegionSize; x++)
+ if (reader.Read())
{
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terrain[x, y] = br.ReadDouble();
- }
+ int rev = (int)reader["Revision"];
+ byte[] blob = (byte[])reader["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
- rev = (int)reader["Revision"];
+ else
+ {
+ _Log.Info("[REGION DB]: No terrain found for region");
+ return null;
+ }
+ _Log.Info("[REGION DB]: Loaded terrain");
}
- else
- {
- _Log.Info("[REGION DB]: No terrain found for region");
- return null;
- }
- _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
}
}
- return terrain;
+ return terrData;
+ }
+
+ // Legacy entry point for when terrain was always a 256x256 hieghtmap
+ public void StoreTerrain(double[,] ter, UUID regionID)
+ {
+ StoreTerrain(new HeightmapTerrainData(ter), regionID);
}
///
@@ -574,10 +583,8 @@ ELSE
///
/// terrain map data.
/// regionID.
- public void StoreTerrain(double[,] terrain, UUID regionID)
+ public void StoreTerrain(TerrainData terrData, UUID regionID)
{
- int revision = Util.UnixTimeSinceEpoch();
-
//Delete old terrain map
string sql = "delete from terrain where RegionUUID=@RegionUUID";
using (SqlConnection conn = new SqlConnection(m_connectionString))
@@ -590,17 +597,23 @@ ELSE
sql = "insert into terrain(RegionUUID, Revision, Heightfield) values(@RegionUUID, @Revision, @Heightfield)";
+ int terrainDBRevision;
+ Array terrainDBblob;
+ terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
+
using (SqlConnection conn = new SqlConnection(m_connectionString))
- using (SqlCommand cmd = new SqlCommand(sql, conn))
{
- cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
- cmd.Parameters.Add(_Database.CreateParameter("@Revision", revision));
- cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", serializeTerrain(terrain)));
- conn.Open();
- cmd.ExecuteNonQuery();
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID));
+ cmd.Parameters.Add(_Database.CreateParameter("@Revision", terrainDBRevision));
+ cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", terrainDBblob));
+ conn.Open();
+ cmd.ExecuteNonQuery();
+ }
}
- _Log.Info("[REGION DB]: Stored terrain revision r " + revision);
+ _Log.Info("[REGION DB]: Stored terrain");
}
///
@@ -1344,6 +1357,7 @@ VALUES
#region Private Methods
+ /*
///
/// Serializes the terrain data for storage in DB.
///
@@ -1367,6 +1381,7 @@ VALUES
return str.ToArray();
}
+ */
///
/// Stores new regionsettings.
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index cc844aef76..f910e443fc 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -48,8 +48,18 @@ namespace OpenSim.Data.MySQL
public class MySQLSimulationData : ISimulationDataStore
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static string LogHeader = "[REGION DB MYSQL]";
private string m_connectionString;
+
+ ///
+ /// This lock was being used to serialize database operations when the connection was shared, but this has
+ /// been unnecessary for a long time after we switched to using MySQL's underlying connection pooling instead.
+ /// FIXME: However, the locks remain in many places since they are effectively providing a level of
+ /// transactionality. This should be replaced by more efficient database transactions which would not require
+ /// unrelated operations to block each other or unrelated operations on the same tables from blocking each
+ /// other.
+ ///
private object m_dbLock = new object();
protected virtual Assembly Assembly
@@ -91,7 +101,7 @@ namespace OpenSim.Data.MySQL
}
catch (Exception e)
{
- m_log.Error("[REGION DB]: MySQL error in ExecuteReader: " + e.Message);
+ m_log.ErrorFormat("{0} MySQL error in ExecuteReader: {1}", LogHeader, e);
throw;
}
@@ -574,12 +584,16 @@ namespace OpenSim.Data.MySQL
}
}
- public virtual void StoreTerrain(double[,] ter, UUID regionID)
+ // Legacy entry point for when terrain was always a 256x256 hieghtmap
+ public void StoreTerrain(double[,] ter, UUID regionID)
+ {
+ StoreTerrain(new HeightmapTerrainData(ter), regionID);
+ }
+
+ public void StoreTerrain(TerrainData terrData, UUID regionID)
{
Util.FireAndForget(delegate(object x)
{
- double[,] oldTerrain = LoadTerrain(regionID);
-
m_log.Info("[REGION DB]: Storing terrain");
lock (m_dbLock)
@@ -601,8 +615,12 @@ namespace OpenSim.Data.MySQL
"Revision, Heightfield) values (?RegionUUID, " +
"1, ?Heightfield)";
- cmd2.Parameters.AddWithValue("RegionUUID", regionID.ToString());
- cmd2.Parameters.AddWithValue("Heightfield", SerializeTerrain(ter, oldTerrain));
+ int terrainDBRevision;
+ Array terrainDBblob;
+ terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
+
+ cmd2.Parameters.AddWithValue("Revision", terrainDBRevision);
+ cmd2.Parameters.AddWithValue("Heightfield", terrainDBblob);
ExecuteNonQuery(cmd);
ExecuteNonQuery(cmd2);
@@ -618,9 +636,20 @@ namespace OpenSim.Data.MySQL
});
}
+ // Legacy region loading
public virtual double[,] LoadTerrain(UUID regionID)
{
- double[,] terrain = null;
+ double[,] ret = null;
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ if (terrData != null)
+ ret = terrData.GetDoubles();
+ return ret;
+ }
+
+ // Returns 'null' if region not found
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
lock (m_dbLock)
{
@@ -640,32 +669,15 @@ namespace OpenSim.Data.MySQL
while (reader.Read())
{
int rev = Convert.ToInt32(reader["Revision"]);
-
- terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terrain.Initialize();
-
- using (MemoryStream mstr = new MemoryStream((byte[])reader["Heightfield"]))
- {
- using (BinaryReader br = new BinaryReader(mstr))
- {
- for (int x = 0; x < (int)Constants.RegionSize; x++)
- {
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terrain[x, y] = br.ReadDouble();
- }
- }
- }
-
- m_log.InfoFormat("[REGION DB]: Loaded terrain revision r{0}", rev);
- }
+ byte[] blob = (byte[])reader["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
}
}
}
}
- return terrain;
+ return terrData;
}
public virtual void RemoveLandObject(UUID globalID)
diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs
index 15824a9ebe..339e7f45b0 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -132,15 +132,33 @@ namespace OpenSim.Data.Null
return new List();
}
- Dictionary m_terrains = new Dictionary();
- public void StoreTerrain(double[,] ter, UUID regionID)
+ Dictionary m_terrains = new Dictionary();
+ public void StoreTerrain(TerrainData ter, UUID regionID)
{
if (m_terrains.ContainsKey(regionID))
m_terrains.Remove(regionID);
m_terrains.Add(regionID, ter);
}
+ // Legacy. Just don't do this.
+ public void StoreTerrain(double[,] ter, UUID regionID)
+ {
+ TerrainData terrData = new HeightmapTerrainData(ter);
+ StoreTerrain(terrData, regionID);
+ }
+
+ // Legacy. Just don't do this.
+ // Returns 'null' if region not found
public double[,] LoadTerrain(UUID regionID)
+ {
+ if (m_terrains.ContainsKey(regionID))
+ {
+ return m_terrains[regionID].GetDoubles();
+ }
+ return null;
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
{
if (m_terrains.ContainsKey(regionID))
{
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
index 3243635a3a..cd02e058bc 100644
--- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
+++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
@@ -46,6 +46,7 @@ namespace OpenSim.Data.PGSQL
public class PGSQLSimulationData : ISimulationDataStore
{
private const string _migrationStore = "RegionStore";
+ private const string LogHeader = "[REGION DB PGSQL]";
// private static FileSystemDataStore Instance = new FileSystemDataStore();
private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -523,8 +524,17 @@ namespace OpenSim.Data.PGSQL
///
public double[,] LoadTerrain(UUID regionID)
{
- double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terrain.Initialize();
+ double[,] ret = null;
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ if (terrData != null)
+ ret = terrData.GetDoubles();
+ return ret;
+ }
+
+ // Returns 'null' if region not found
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
string sql = @"select ""RegionUUID"", ""Revision"", ""Heightfield"" from terrain
where ""RegionUUID"" = :RegionUUID order by ""Revision"" desc limit 1; ";
@@ -540,16 +550,9 @@ namespace OpenSim.Data.PGSQL
int rev;
if (reader.Read())
{
- MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
- BinaryReader br = new BinaryReader(str);
- for (int x = 0; x < (int)Constants.RegionSize; x++)
- {
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terrain[x, y] = br.ReadDouble();
- }
- }
- rev = (int)reader["Revision"];
+ rev = Convert.ToInt32(reader["Revision"]);
+ byte[] blob = (byte[])reader["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
else
{
@@ -560,7 +563,13 @@ namespace OpenSim.Data.PGSQL
}
}
- return terrain;
+ return terrData;
+ }
+
+ // Legacy entry point for when terrain was always a 256x256 heightmap
+ public void StoreTerrain(double[,] terrain, UUID regionID)
+ {
+ StoreTerrain(new HeightmapTerrainData(terrain), regionID);
}
///
@@ -568,35 +577,38 @@ namespace OpenSim.Data.PGSQL
///
/// terrain map data.
/// regionID.
- public void StoreTerrain(double[,] terrain, UUID regionID)
+ public void StoreTerrain(TerrainData terrData, UUID regionID)
{
- int revision = Util.UnixTimeSinceEpoch();
-
//Delete old terrain map
string sql = @"delete from terrain where ""RegionUUID""=:RegionUUID";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
- using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
- cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
- conn.Open();
- cmd.ExecuteNonQuery();
+ using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
+ {
+ cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
+ conn.Open();
+ cmd.ExecuteNonQuery();
+ }
}
-
- _Log.Info("[REGION DB]: Deleted terrain revision r " + revision);
+ int terrainDBRevision;
+ Array terrainDBblob;
+ terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
sql = @"insert into terrain(""RegionUUID"", ""Revision"", ""Heightfield"") values(:RegionUUID, :Revision, :Heightfield)";
using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
- using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
{
- cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
- cmd.Parameters.Add(_Database.CreateParameter("Revision", revision));
- cmd.Parameters.Add(_Database.CreateParameter("Heightfield", serializeTerrain(terrain)));
- conn.Open();
- cmd.ExecuteNonQuery();
+ using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
+ {
+ cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
+ cmd.Parameters.Add(_Database.CreateParameter("Revision", terrainDBRevision));
+ cmd.Parameters.Add(_Database.CreateParameter("Heightfield", terrainDBblob));
+ conn.Open();
+ cmd.ExecuteNonQuery();
+ }
}
- _Log.Info("[REGION DB]: Stored terrain revision r " + revision);
+ _Log.Info("[REGION DB]: Stored terrain revision r " + terrainDBRevision);
}
///
@@ -1349,6 +1361,7 @@ namespace OpenSim.Data.PGSQL
#region Private Methods
+ /*
///
/// Serializes the terrain data for storage in DB.
///
@@ -1372,6 +1385,7 @@ namespace OpenSim.Data.PGSQL
return str.ToArray();
}
+ */
///
/// Stores new regionsettings.
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 4d6a80ad22..d28c2277e0 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -51,6 +51,7 @@ namespace OpenSim.Data.SQLite
public class SQLiteSimulationData : ISimulationDataStore
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly string LogHeader = "[REGION DB SQLLITE]";
private const string primSelect = "select * from prims";
private const string shapeSelect = "select * from primshapes";
@@ -819,12 +820,18 @@ namespace OpenSim.Data.SQLite
prim.Inventory.RestoreInventoryItems(inventory);
}
+ // Legacy entry point for when terrain was always a 256x256 hieghtmap
+ public void StoreTerrain(double[,] ter, UUID regionID)
+ {
+ StoreTerrain(new HeightmapTerrainData(ter), regionID);
+ }
+
///
/// Store a terrain revision in region storage
///
/// terrain heightfield
/// region UUID
- public void StoreTerrain(double[,] ter, UUID regionID)
+ public void StoreTerrain(TerrainData terrData, UUID regionID)
{
lock (ds)
{
@@ -853,11 +860,17 @@ namespace OpenSim.Data.SQLite
String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" +
" values(:RegionUUID, :Revision, :Heightfield)";
+ int terrainDBRevision;
+ Array terrainDBblob;
+ terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
+
+ m_log.DebugFormat("{0} Storing terrain revision r {1}", LogHeader, terrainDBRevision);
+
using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
{
cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
- cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
- cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter)));
+ cmd.Parameters.Add(new SqliteParameter(":Revision", terrainDBRevision));
+ cmd.Parameters.Add(new SqliteParameter(":Heightfield", terrainDBblob));
cmd.ExecuteNonQuery();
}
}
@@ -870,11 +883,20 @@ namespace OpenSim.Data.SQLite
/// Heightfield data
public double[,] LoadTerrain(UUID regionID)
{
+ double[,] ret = null;
+ TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ if (terrData != null)
+ ret = terrData.GetDoubles();
+ return ret;
+ }
+
+ // Returns 'null' if region not found
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ TerrainData terrData = null;
+
lock (ds)
{
- double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
- terret.Initialize();
-
String sql = "select RegionUUID, Revision, Heightfield from terrain" +
" where RegionUUID=:RegionUUID order by Revision desc";
@@ -887,21 +909,9 @@ namespace OpenSim.Data.SQLite
int rev = 0;
if (row.Read())
{
- // TODO: put this into a function
- using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"]))
- {
- using (BinaryReader br = new BinaryReader(str))
- {
- for (int x = 0; x < (int)Constants.RegionSize; x++)
- {
- for (int y = 0; y < (int)Constants.RegionSize; y++)
- {
- terret[x, y] = br.ReadDouble();
- }
- }
- }
- }
rev = Convert.ToInt32(row["Revision"]);
+ byte[] blob = (byte[])row["Heightfield"];
+ terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
}
else
{
@@ -912,8 +922,8 @@ namespace OpenSim.Data.SQLite
m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString());
}
}
- return terret;
}
+ return terrData;
}
public void RemoveLandObject(UUID globalID)
@@ -2016,6 +2026,7 @@ namespace OpenSim.Data.SQLite
return entry;
}
+ /*
///
///
///
@@ -2033,6 +2044,7 @@ namespace OpenSim.Data.SQLite
return str.ToArray();
}
+ */
// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val)
// {
diff --git a/OpenSim/Framework/MapBlockData.cs b/OpenSim/Framework/MapBlockData.cs
index 2298ac57e2..4bee4995f3 100644
--- a/OpenSim/Framework/MapBlockData.cs
+++ b/OpenSim/Framework/MapBlockData.cs
@@ -27,6 +27,7 @@
using System;
using OpenMetaverse;
+using OpenMetaverse.StructuredData;
namespace OpenSim.Framework
{
@@ -40,9 +41,26 @@ namespace OpenSim.Framework
public byte WaterHeight;
public ushort X;
public ushort Y;
+ public ushort SizeX;
+ public ushort SizeY;
public MapBlockData()
{
}
+
+ public OSDMap ToOSD()
+ {
+ OSDMap map = new OSDMap();
+ map["X"] = X;
+ map["Y"] = Y;
+ map["SizeX"] = SizeX;
+ map["SizeY"] = SizeY;
+ map["Name"] = Name;
+ map["Access"] = Access;
+ map["RegionFlags"] = RegionFlags;
+ map["WaterHeight"] = WaterHeight;
+ map["MapImageID"] = MapImageId;
+ return map;
+ }
}
}
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index ae2ff639eb..019fffc8ba 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -149,11 +149,32 @@ namespace OpenSim.Framework
public uint WorldLocX = 0;
public uint WorldLocY = 0;
public uint WorldLocZ = 0;
+
+ ///
+ /// X dimension of the region.
+ ///
+ ///
+ /// If this is a varregion then the default size set here will be replaced when we load the region config.
+ ///
public uint RegionSizeX = Constants.RegionSize;
+
+ ///
+ /// X dimension of the region.
+ ///
+ ///
+ /// If this is a varregion then the default size set here will be replaced when we load the region config.
+ ///
public uint RegionSizeY = Constants.RegionSize;
+
+ ///
+ /// Z dimension of the region.
+ ///
+ ///
+ /// XXX: Unknown if this accounts for regions with negative Z.
+ ///
public uint RegionSizeZ = Constants.RegionHeight;
- private Dictionary m_otherSettings = new Dictionary();
+ private Dictionary m_extraSettings = new Dictionary();
// Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
@@ -506,16 +527,16 @@ namespace OpenSim.Framework
{
string val;
string keylower = key.ToLower();
- if (m_otherSettings.TryGetValue(keylower, out val))
+ if (m_extraSettings.TryGetValue(keylower, out val))
return val;
m_log.DebugFormat("[RegionInfo] Could not locate value for parameter {0}", key);
return null;
}
- public void SetOtherSetting(string key, string value)
+ public void SetExtraSetting(string key, string value)
{
string keylower = key.ToLower();
- m_otherSettings[keylower] = value;
+ m_extraSettings[keylower] = value;
}
private void ReadNiniConfig(IConfigSource source, string name)
@@ -733,7 +754,7 @@ namespace OpenSim.Framework
foreach (String s in allKeys)
{
- SetOtherSetting(s, config.GetString(s));
+ SetExtraSetting(s, config.GetString(s));
}
}
@@ -804,6 +825,7 @@ namespace OpenSim.Framework
if (DataStore != String.Empty)
config.Set("Datastore", DataStore);
+
if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
{
config.Set("SizeX", RegionSizeX);
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
new file mode 100644
index 0000000000..6b1be4e9fa
--- /dev/null
+++ b/OpenSim/Framework/TerrainData.cs
@@ -0,0 +1,464 @@
+/*
+ * 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.IO;
+using System.Reflection;
+
+using OpenMetaverse;
+
+using log4net;
+
+namespace OpenSim.Framework
+{
+ public abstract class TerrainData
+ {
+ // Terrain always is a square
+ public int SizeX { get; protected set; }
+ public int SizeY { get; protected set; }
+ public int SizeZ { get; protected set; }
+
+ // A height used when the user doesn't specify anything
+ public const float DefaultTerrainHeight = 21f;
+
+ public abstract float this[int x, int y] { get; set; }
+ // Someday terrain will have caves
+ public abstract float this[int x, int y, int z] { get; set; }
+
+ public abstract bool IsTaintedAt(int xx, int yy);
+ public abstract bool IsTaintedAt(int xx, int yy, bool clearOnTest);
+ public abstract void TaintAllTerrain();
+ public abstract void ClearTaint();
+
+ public abstract void ClearLand();
+ public abstract void ClearLand(float height);
+
+ // Return a representation of this terrain for storing as a blob in the database.
+ // Returns 'true' to say blob was stored in the 'out' locations.
+ public abstract bool GetDatabaseBlob(out int DBFormatRevisionCode, out Array blob);
+
+ // Given a revision code and a blob from the database, create and return the right type of TerrainData.
+ // The sizes passed are the expected size of the region. The database info will be used to
+ // initialize the heightmap of that sized region with as much data is in the blob.
+ // Return created TerrainData or 'null' if unsuccessful.
+ public static TerrainData CreateFromDatabaseBlobFactory(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob)
+ {
+ // For the moment, there is only one implementation class
+ return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob);
+ }
+
+ // return a special compressed representation of the heightmap in ints
+ public abstract int[] GetCompressedMap();
+ public abstract float CompressionFactor { get; }
+
+ public abstract float[] GetFloatsSerialized();
+ public abstract double[,] GetDoubles();
+ public abstract TerrainData Clone();
+ }
+
+ // The terrain is stored in the database as a blob with a 'revision' field.
+ // Some implementations of terrain storage would fill the revision field with
+ // the time the terrain was stored. When real revisions were added and this
+ // feature removed, that left some old entries with the time in the revision
+ // field.
+ // Thus, if revision is greater than 'RevisionHigh' then terrain db entry is
+ // left over and it is presumed to be 'Legacy256'.
+ // Numbers are arbitrary and are chosen to to reduce possible mis-interpretation.
+ // If a revision does not match any of these, it is assumed to be Legacy256.
+ public enum DBTerrainRevision
+ {
+ // Terrain is 'double[256,256]'
+ Legacy256 = 11,
+ // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions
+ // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
+ Variable2D = 22,
+ // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions
+ // and third int is the 'compression factor'. The heights are compressed as
+ // "int compressedHeight = (int)(height * compressionFactor);"
+ // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
+ Compressed2D = 27,
+ // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
+ RevisionHigh = 1234
+ }
+
+ // Version of terrain that is a heightmap.
+ // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
+ // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer.
+ // The heighmap is kept as an array of integers. The integer values are converted to
+ // and from floats by TerrainCompressionFactor.
+ public class HeightmapTerrainData : TerrainData
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static string LogHeader = "[HEIGHTMAP TERRAIN DATA]";
+
+ // TerrainData.this[x, y]
+ public override float this[int x, int y]
+ {
+ get { return FromCompressedHeight(m_heightmap[x, y]); }
+ set {
+ int newVal = ToCompressedHeight(value);
+ if (m_heightmap[x, y] != newVal)
+ {
+ m_heightmap[x, y] = newVal;
+ m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
+ }
+ }
+ }
+
+ // TerrainData.this[x, y, z]
+ public override float this[int x, int y, int z]
+ {
+ get { return this[x, y]; }
+ set { this[x, y] = value; }
+ }
+
+ // TerrainData.ClearTaint
+ public override void ClearTaint()
+ {
+ SetAllTaint(false);
+ }
+
+ // TerrainData.TaintAllTerrain
+ public override void TaintAllTerrain()
+ {
+ SetAllTaint(true);
+ }
+
+ private void SetAllTaint(bool setting)
+ {
+ for (int ii = 0; ii < m_taint.GetLength(0); ii++)
+ for (int jj = 0; jj < m_taint.GetLength(1); jj++)
+ m_taint[ii, jj] = setting;
+ }
+
+ // TerrainData.ClearLand
+ public override void ClearLand()
+ {
+ ClearLand(DefaultTerrainHeight);
+ }
+ // TerrainData.ClearLand(float)
+ public override void ClearLand(float pHeight)
+ {
+ int flatHeight = ToCompressedHeight(pHeight);
+ for (int xx = 0; xx < SizeX; xx++)
+ for (int yy = 0; yy < SizeY; yy++)
+ m_heightmap[xx, yy] = flatHeight;
+ }
+
+ // Return 'true' of the patch that contains these region coordinates has been modified.
+ // Note that checking the taint clears it.
+ // There is existing code that relies on this feature.
+ public override bool IsTaintedAt(int xx, int yy, bool clearOnTest)
+ {
+ int tx = xx / Constants.TerrainPatchSize;
+ int ty = yy / Constants.TerrainPatchSize;
+ bool ret = m_taint[tx, ty];
+ if (ret && clearOnTest)
+ m_taint[tx, ty] = false;
+ return ret;
+ }
+
+ // Old form that clears the taint flag when we check it.
+ public override bool IsTaintedAt(int xx, int yy)
+ {
+ return IsTaintedAt(xx, yy, true /* clearOnTest */);
+ }
+
+ // TerrainData.GetDatabaseBlob
+ // The user wants something to store in the database.
+ public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
+ {
+ bool ret = false;
+ if (SizeX == Constants.RegionSize && SizeY == Constants.RegionSize)
+ {
+ DBRevisionCode = (int)DBTerrainRevision.Legacy256;
+ blob = ToLegacyTerrainSerialization();
+ ret = true;
+ }
+ else
+ {
+ DBRevisionCode = (int)DBTerrainRevision.Compressed2D;
+ blob = ToCompressedTerrainSerialization();
+ ret = true;
+ }
+ return ret;
+ }
+
+ // TerrainData.CompressionFactor
+ private float m_compressionFactor = 100.0f;
+ public override float CompressionFactor { get { return m_compressionFactor; } }
+
+ // TerrainData.GetCompressedMap
+ public override int[] GetCompressedMap()
+ {
+ int[] newMap = new int[SizeX * SizeY];
+
+ int ind = 0;
+ for (int xx = 0; xx < SizeX; xx++)
+ for (int yy = 0; yy < SizeY; yy++)
+ newMap[ind++] = m_heightmap[xx, yy];
+
+ return newMap;
+
+ }
+ // TerrainData.Clone
+ public override TerrainData Clone()
+ {
+ HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
+ ret.m_heightmap = (int[,])this.m_heightmap.Clone();
+ return ret;
+ }
+
+ // TerrainData.GetFloatsSerialized
+ // This one dimensional version is ordered so height = map[y*sizeX+x];
+ // DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
+ // and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
+ public override float[] GetFloatsSerialized()
+ {
+ int points = SizeX * SizeY;
+ float[] heights = new float[points];
+
+ int idx = 0;
+ for (int jj = 0; jj < SizeY; jj++)
+ for (int ii = 0; ii < SizeX; ii++)
+ {
+ heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]);
+ }
+
+ return heights;
+ }
+
+ // TerrainData.GetDoubles
+ public override double[,] GetDoubles()
+ {
+ double[,] ret = new double[SizeX, SizeY];
+ for (int xx = 0; xx < SizeX; xx++)
+ for (int yy = 0; yy < SizeY; yy++)
+ ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]);
+
+ return ret;
+ }
+
+
+ // =============================================================
+
+ private int[,] m_heightmap;
+ // Remember subregions of the heightmap that has changed.
+ private bool[,] m_taint;
+
+ // To save space (especially for large regions), keep the height as a short integer
+ // that is coded as the float height times the compression factor (usually '100'
+ // to make for two decimal points).
+ public int ToCompressedHeight(double pHeight)
+ {
+ return (int)(pHeight * CompressionFactor);
+ }
+
+ public float FromCompressedHeight(int pHeight)
+ {
+ return ((float)pHeight) / CompressionFactor;
+ }
+
+ // To keep with the legacy theme, create an instance of this class based on the
+ // way terrain used to be passed around.
+ public HeightmapTerrainData(double[,] pTerrain)
+ {
+ SizeX = pTerrain.GetLength(0);
+ SizeY = pTerrain.GetLength(1);
+ SizeZ = (int)Constants.RegionHeight;
+ m_compressionFactor = 100.0f;
+
+ m_heightmap = new int[SizeX, SizeY];
+ for (int ii = 0; ii < SizeX; ii++)
+ {
+ for (int jj = 0; jj < SizeY; jj++)
+ {
+ m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]);
+
+ }
+ }
+ // m_log.DebugFormat("{0} new by doubles. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
+
+ m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
+ ClearTaint();
+ }
+
+ // Create underlying structures but don't initialize the heightmap assuming the caller will immediately do that
+ public HeightmapTerrainData(int pX, int pY, int pZ)
+ {
+ SizeX = pX;
+ SizeY = pY;
+ SizeZ = pZ;
+ m_compressionFactor = 100.0f;
+ m_heightmap = new int[SizeX, SizeY];
+ m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
+ // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
+ ClearTaint();
+ ClearLand(0f);
+ }
+
+ public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ)
+ {
+ m_compressionFactor = pCompressionFactor;
+ int ind = 0;
+ for (int xx = 0; xx < SizeX; xx++)
+ for (int yy = 0; yy < SizeY; yy++)
+ m_heightmap[xx, yy] = cmap[ind++];
+ // m_log.DebugFormat("{0} new by compressed map. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
+ }
+
+ // Create a heighmap from a database blob
+ public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ)
+ {
+ switch ((DBTerrainRevision)pFormatCode)
+ {
+ case DBTerrainRevision.Compressed2D:
+ FromCompressedTerrainSerialization(pBlob);
+ m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
+ break;
+ default:
+ FromLegacyTerrainSerialization(pBlob);
+ m_log.DebugFormat("{0} HeightmapTerrainData create from legacy serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
+ break;
+ }
+ }
+
+ // Just create an array of doubles. Presumes the caller implicitly knows the size.
+ public Array ToLegacyTerrainSerialization()
+ {
+ Array ret = null;
+
+ using (MemoryStream str = new MemoryStream((int)Constants.RegionSize * (int)Constants.RegionSize * sizeof(double)))
+ {
+ using (BinaryWriter bw = new BinaryWriter(str))
+ {
+ for (int xx = 0; xx < Constants.RegionSize; xx++)
+ {
+ for (int yy = 0; yy < Constants.RegionSize; yy++)
+ {
+ double height = this[xx, yy];
+ if (height == 0.0)
+ height = double.Epsilon;
+ bw.Write(height);
+ }
+ }
+ }
+ ret = str.ToArray();
+ }
+ return ret;
+ }
+
+ // Just create an array of doubles. Presumes the caller implicitly knows the size.
+ public void FromLegacyTerrainSerialization(byte[] pBlob)
+ {
+ // In case database info doesn't match real terrain size, initialize the whole terrain.
+ ClearLand();
+
+ using (MemoryStream mstr = new MemoryStream(pBlob))
+ {
+ using (BinaryReader br = new BinaryReader(mstr))
+ {
+ for (int xx = 0; xx < (int)Constants.RegionSize; xx++)
+ {
+ for (int yy = 0; yy < (int)Constants.RegionSize; yy++)
+ {
+ float val = (float)br.ReadDouble();
+ if (xx < SizeX && yy < SizeY)
+ m_heightmap[xx, yy] = ToCompressedHeight(val);
+ }
+ }
+ }
+ ClearTaint();
+ }
+ }
+
+ // See the reader below.
+ public Array ToCompressedTerrainSerialization()
+ {
+ Array ret = null;
+ using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16))))
+ {
+ using (BinaryWriter bw = new BinaryWriter(str))
+ {
+ bw.Write((Int32)DBTerrainRevision.Compressed2D);
+ bw.Write((Int32)SizeX);
+ bw.Write((Int32)SizeY);
+ bw.Write((Int32)CompressionFactor);
+ for (int yy = 0; yy < SizeY; yy++)
+ for (int xx = 0; xx < SizeX; xx++)
+ {
+ bw.Write((Int16)m_heightmap[xx, yy]);
+ }
+ }
+ ret = str.ToArray();
+ }
+ return ret;
+ }
+
+ // Initialize heightmap from blob consisting of:
+ // int32, int32, int32, int32, int16[]
+ // where the first int32 is format code, next two int32s are the X and y of heightmap data and
+ // the forth int is the compression factor for the following int16s
+ // This is just sets heightmap info. The actual size of the region was set on this instance's
+ // creation and any heights not initialized by theis blob are set to the default height.
+ public void FromCompressedTerrainSerialization(byte[] pBlob)
+ {
+ Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
+
+ using (MemoryStream mstr = new MemoryStream(pBlob))
+ {
+ using (BinaryReader br = new BinaryReader(mstr))
+ {
+ hmFormatCode = br.ReadInt32();
+ hmSizeX = br.ReadInt32();
+ hmSizeY = br.ReadInt32();
+ hmCompressionFactor = br.ReadInt32();
+
+ m_compressionFactor = hmCompressionFactor;
+
+ // In case database info doesn't match real terrain size, initialize the whole terrain.
+ ClearLand();
+
+ for (int yy = 0; yy < hmSizeY; yy++)
+ {
+ for (int xx = 0; xx < hmSizeX; xx++)
+ {
+ Int16 val = br.ReadInt16();
+ if (xx < SizeX && yy < SizeY)
+ m_heightmap[xx, yy] = val;
+ }
+ }
+ }
+ ClearTaint();
+
+ m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}",
+ LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
+ }
+ }
+ }
+}
diff --git a/OpenSim/Framework/UserProfileData.cs b/OpenSim/Framework/UserProfileData.cs
index 9bac739589..f7069a56a2 100644
--- a/OpenSim/Framework/UserProfileData.cs
+++ b/OpenSim/Framework/UserProfileData.cs
@@ -161,14 +161,18 @@ namespace OpenSim.Framework
{
get
{
- return Utils.UIntsToLong(
- m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
+ return Util.RegionWorldLocToHandle(Util.RegionToWorldLoc(m_homeRegionX), Util.RegionToWorldLoc(m_homeRegionY));
+ // return Utils.UIntsToLong( m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
}
set
{
- m_homeRegionX = (uint) (value >> 40);
- m_homeRegionY = (((uint) (value)) >> 8);
+ uint regionWorldLocX, regionWorldLocY;
+ Util.RegionHandleToWorldLoc(value, out regionWorldLocX, out regionWorldLocY);
+ m_homeRegionX = Util.WorldToRegionLoc(regionWorldLocX);
+ m_homeRegionY = Util.WorldToRegionLoc(regionWorldLocY);
+ // m_homeRegionX = (uint) (value >> 40);
+ // m_homeRegionY = (((uint) (value)) >> 8);
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index ca6c3ca1a7..51535a665b 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -59,6 +59,7 @@ namespace OpenSim.Region.ClientStack.Linden
public class EventQueueGetModule : IEventQueue, INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static string LogHeader = "[EVENT QUEUE GET MODULE]";
///
/// Debug level.
@@ -479,7 +480,7 @@ namespace OpenSim.Region.ClientStack.Linden
public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
- "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
+ LogHeader, handle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
Enqueue(item, avatarID);
@@ -489,7 +490,7 @@ namespace OpenSim.Region.ClientStack.Linden
ulong regionHandle, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
- "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
+ LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
Enqueue(item, avatarID);
}
@@ -500,7 +501,7 @@ namespace OpenSim.Region.ClientStack.Linden
UUID avatarID, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize={3},{4}>",
- "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
+ LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
@@ -512,7 +513,7 @@ namespace OpenSim.Region.ClientStack.Linden
string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
{
m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
- "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
+ LogHeader, handle, avatarID, regionSizeX, regionSizeY);
OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 7b6889ab09..226f2a1aca 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -312,6 +312,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static string LogHeader = "[LLCLIENTVIEW]";
protected static Dictionary PacketHandlers = new Dictionary(); //Global/static handlers for all clients
///
@@ -691,13 +692,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
/// true if the handler was added. This is currently always the case.
public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync)
+ {
+ return AddLocalPacketHandler(packetType, handler, doAsync, false);
+ }
+
+ ///
+ /// Add a handler for the given packet type.
+ ///
+ ///
+ ///
+ ///
+ /// If true, when the packet is received handle it on a different thread. Whether this is given direct to
+ /// a threadpool thread or placed in a queue depends on the inEngine parameter.
+ ///
+ ///
+ /// If async is false then this parameter is ignored.
+ /// If async is true and inEngine is false, then the packet is sent directly to a
+ /// threadpool thread.
+ /// If async is true and inEngine is true, then the packet is sent to the IncomingPacketAsyncHandlingEngine.
+ /// This may result in slower handling but reduces the risk of overloading the simulator when there are many
+ /// simultaneous async requests.
+ ///
+ /// true if the handler was added. This is currently always the case.
+ public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync, bool inEngine)
{
bool result = false;
lock (m_packetHandlers)
{
if (!m_packetHandlers.ContainsKey(packetType))
{
- m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = doAsync });
+ m_packetHandlers.Add(
+ packetType, new PacketProcessor() { method = handler, Async = doAsync });
result = true;
}
}
@@ -1176,11 +1201,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
/// Send the region heightmap to the client
+ /// This method is only called when not doing intellegent terrain patch sending and
+ /// is only called when the scene presence is initially created and sends all of the
+ /// region's patches to the client.
///
/// heightmap
public virtual void SendLayerData(float[] map)
{
- Util.FireAndForget(DoSendLayerData, map);
+ Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData());
// Send it sync, and async. It's not that much data
// and it improves user experience just so much!
@@ -1193,15 +1221,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
private void DoSendLayerData(object o)
{
- float[] map = LLHeightFieldMoronize((float[])o);
+ TerrainData map = (TerrainData)o;
try
{
+ // Send LayerData in typerwriter pattern
for (int y = 0; y < 16; y++)
{
- for (int x = 0; x < 16; x+=4)
+ for (int x = 0; x < 16; x++)
{
- SendLayerPacket(x, y, map);
+ SendLayerData(x, y, map);
}
}
}
@@ -1211,77 +1240,95 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
- ///
- /// Sends a set of four patches (x, x+1, ..., x+3) to the client
- ///
- /// heightmap
- /// X coordinate for patches 0..12
- /// Y coordinate for patches 0..15
- private void SendLayerPacket(int x, int y, float[] map)
+ // Legacy form of invocation that passes around a bare data array.
+ // Just ignore what was passed and use the real terrain info that is part of the scene.
+ // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI,
+ // there is a special form for specifying multiple terrain patches to send.
+ // The form is to pass 'px' as negative the number of patches to send and to
+ // pass the float array as pairs of patch X and Y coordinates. So, passing 'px'
+ // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches
+ // and the patches to send are <3,5> and <8,4>.
+ public void SendLayerData(int px, int py, float[] map)
{
- int[] patches = new int[4];
- patches[0] = x + 0 + y * 16;
- patches[1] = x + 1 + y * 16;
- patches[2] = x + 2 + y * 16;
- patches[3] = x + 3 + y * 16;
-
- float[] heightmap = (map.Length == 65536) ?
- map :
- LLHeightFieldMoronize(map);
-
- try
+ if (px >= 0)
{
- Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
- OutPacket(layerpack, ThrottleOutPacketType.Land);
+ SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
}
- catch
+ else
{
- for (int px = x ; px < x + 4 ; px++)
- SendLayerData(px, y, map);
+ int numPatches = -px;
+ int[] xPatches = new int[numPatches];
+ int[] yPatches = new int[numPatches];
+ for (int pp = 0; pp < numPatches; pp++)
+ {
+ xPatches[pp] = (int)map[pp * 2];
+ yPatches[pp] = (int)map[pp * 2 + 1];
+ }
+
+ // DebugSendingPatches("SendLayerData", xPatches, yPatches);
+
+ SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData());
+ }
+ }
+
+ private void DebugSendingPatches(string pWho, int[] pX, int[] pY)
+ {
+ if (m_log.IsDebugEnabled)
+ {
+ int numPatches = pX.Length;
+ string Xs = "";
+ string Ys = "";
+ for (int pp = 0; pp < numPatches; pp++)
+ {
+ Xs += String.Format("{0}", (int)pX[pp]) + ",";
+ Ys += String.Format("{0}", (int)pY[pp]) + ",";
+ }
+ m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys);
}
}
///
- /// Sends a specified patch to a client
+ /// Sends a terrain packet for the point specified.
+ /// This is a legacy call that has refarbed the terrain into a flat map of floats.
+ /// We just use the terrain from the region we know about.
///
/// Patch coordinate (x) 0..15
/// Patch coordinate (y) 0..15
/// heightmap
- public void SendLayerData(int px, int py, float[] map)
+ public void SendLayerData(int px, int py, TerrainData terrData)
+ {
+ int[] xPatches = new[] { px };
+ int[] yPatches = new[] { py };
+ SendLayerData(xPatches, yPatches, terrData);
+ }
+
+ private void SendLayerData(int[] px, int[] py, TerrainData terrData)
{
try
{
- int[] patches = new int[] { py * 16 + px };
- float[] heightmap = (map.Length == 65536) ?
- map :
- LLHeightFieldMoronize(map);
-
- LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
-
- // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
- // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
- // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
- // invalidating previous packets for that area.
-
- // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
- // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
-
- // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will
- // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
- // patches.
-
- // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
- if (m_justEditedTerrain)
+ /* test code using the terrain compressor in libOpenMetaverse
+ int[] patchInd = new int[1];
+ patchInd[0] = px + (py * Constants.TerrainPatchSize);
+ LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd);
+ */
+ // Many, many patches could have been passed to us. Since the patches will be compressed
+ // into variable sized blocks, we cannot pre-compute how many will fit into one
+ // packet. While some fancy packing algorithm is possible, 4 seems to always fit.
+ int PatchesAssumedToFit = 4;
+ for (int pcnt = 0; pcnt < px.Length; pcnt += PatchesAssumedToFit)
{
- layerpack.Header.Reliable = false;
- OutPacket(layerpack,
- ThrottleOutPacketType.Unknown );
- }
- else
- {
- layerpack.Header.Reliable = true;
- OutPacket(layerpack,
- ThrottleOutPacketType.Task);
+ int remaining = Math.Min(px.Length - pcnt, PatchesAssumedToFit);
+ int[] xPatches = new int[remaining];
+ int[] yPatches = new int[remaining];
+ for (int ii = 0; ii < remaining; ii++)
+ {
+ xPatches[ii] = px[pcnt + ii];
+ yPatches[ii] = py[pcnt + ii];
+ }
+ LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, xPatches, yPatches);
+ // DebugSendingPatches("SendLayerDataInternal", xPatches, yPatches);
+
+ SendTheLayerPacket(layerpack);
}
}
catch (Exception e)
@@ -1290,36 +1337,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
- ///
- /// Munges heightfield into the LLUDP backed in restricted heightfield.
- ///
- /// float array in the base; Constants.RegionSize
- /// float array in the base 256
- internal float[] LLHeightFieldMoronize(float[] map)
+ // When a user edits the terrain, so much data is sent, the data queues up fast and presents a
+ // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we
+ // start skipping the queues until they're done editing the terrain. We also make them
+ // unreliable because it's extremely likely that multiple packets will be sent for a terrain patch
+ // area invalidating previous packets for that area.
+
+ // It's possible for an editing user to flood themselves with edited packets but the majority
+ // of use cases are such that only a tiny percentage of users will be editing the terrain.
+ // Other, non-editing users will see the edits much slower.
+
+ // One last note on this topic, by the time users are going to be editing the terrain, it's
+ // extremely likely that the sim will have rezzed already and therefore this is not likely going
+ // to cause any additional issues with lost packets, objects or terrain patches.
+
+ // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we
+ // only have one cache miss.
+ private void SendTheLayerPacket(LayerDataPacket layerpack)
{
- if (map.Length == 65536)
- return map;
+ if (m_justEditedTerrain)
+ {
+ layerpack.Header.Reliable = false;
+ OutPacket(layerpack, ThrottleOutPacketType.Unknown );
+ }
else
{
- float[] returnmap = new float[65536];
-
- if (map.Length < 65535)
- {
- // rebase the vector stride to 256
- for (int i = 0; i < Constants.RegionSize; i++)
- Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
- }
- else
- {
- for (int i = 0; i < 256; i++)
- Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
- }
-
- //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
-
- return returnmap;
+ layerpack.Header.Reliable = true;
+ OutPacket(layerpack, ThrottleOutPacketType.Land);
}
-
}
///
@@ -1348,21 +1393,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
Vector2[] windSpeeds = (Vector2[])o;
TerrainPatch[] patches = new TerrainPatch[2];
- patches[0] = new TerrainPatch();
- patches[0].Data = new float[16 * 16];
- patches[1] = new TerrainPatch();
- patches[1].Data = new float[16 * 16];
+ patches[0] = new TerrainPatch { Data = new float[16 * 16] };
+ patches[1] = new TerrainPatch { Data = new float[16 * 16] };
- for (int y = 0; y < 16; y++)
+ for (int x = 0; x < 16 * 16; x++)
{
- for (int x = 0; x < 16; x++)
- {
- patches[0].Data[y * 16 + x] = windSpeeds[y * 16 + x].X;
- patches[1].Data[y * 16 + x] = windSpeeds[y * 16 + x].Y;
- }
+ patches[0].Data[x] = windSpeeds[x].X;
+ patches[1].Data[x] = windSpeeds[x].Y;
}
- LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind);
+ byte layerType = (byte)TerrainPatch.LayerType.Wind;
+ if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
+ layerType = (byte)TerrainPatch.LayerType.WindExtended;
+
+ // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType);
+ LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
+ (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
layerpack.Header.Zerocoded = true;
OutPacket(layerpack, ThrottleOutPacketType.Wind);
}
@@ -1386,7 +1432,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
- LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud);
+ byte layerType = (byte)TerrainPatch.LayerType.Cloud;
+ if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
+ layerType = (byte)TerrainPatch.LayerType.CloudExtended;
+
+ // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType);
+ LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
+ (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
layerpack.Header.Zerocoded = true;
OutPacket(layerpack, ThrottleOutPacketType.Cloud);
}
@@ -1491,10 +1543,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
mapReply.Data[i].Access = mapBlocks2[i].Access;
mapReply.Data[i].Agents = mapBlocks2[i].Agents;
- // TODO: hookup varregion sim size here
mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock();
- mapReply.Size[i].SizeX = 256;
- mapReply.Size[i].SizeY = 256;
+ mapReply.Size[i].SizeX = mapBlocks2[i].SizeX;
+ mapReply.Size[i].SizeY = mapBlocks2[i].SizeY;
}
OutPacket(mapReply, ThrottleOutPacketType.Land);
}
@@ -1659,15 +1710,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendKillObject(List localIDs)
{
-// foreach (uint id in localIDs)
-// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
-
- // remove pending entities
- lock (m_entityProps.SyncRoot)
- m_entityProps.Remove(localIDs);
- lock (m_entityUpdates.SyncRoot)
- m_entityUpdates.Remove(localIDs);
-
KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
// TODO: don't create new blocks if recycling an old packet
kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
@@ -9093,6 +9135,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
if (handlerTeleportLocationRequest != null)
{
+ // Adjust teleport location to base of a larger region if requested to teleport to a sub-region
+ uint locX, locY;
+ Util.RegionHandleToWorldLoc(tpLocReq.Info.RegionHandle, out locX, out locY);
+ if ((locX >= m_scene.RegionInfo.WorldLocX)
+ && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX))
+ && (locY >= m_scene.RegionInfo.WorldLocY)
+ && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) )
+ {
+ tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle;
+ tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX;
+ tpLocReq.Info.Position.Y += locY - m_scene.RegionInfo.WorldLocY;
+ }
+
handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
tpLocReq.Info.LookAt, 16);
}
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index dcfc630c5d..9d70063317 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -213,8 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
IScene scene = c.Scene;
UUID destination = c.Destination;
Vector3 fromPos = c.Position;
- Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
- scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
+ Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
bool checkParcelHide = false;
UUID sourceParcelID = UUID.Zero;
@@ -424,8 +423,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
{
Vector3 fromRegionPos = fromPos + regionPos;
Vector3 toRegionPos = presence.AbsolutePosition +
- new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
- presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
+ new Vector3(presence.Scene.RegionInfo.WorldLocX, presence.Scene.RegionInfo.WorldLocY, 0);
int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index db8405bdb2..7177d9b7bd 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -663,8 +663,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
Vector3 avaPos = p.AbsolutePosition;
// Getting the global position for the Avatar
- Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
- remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
+ Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.WorldLocX + avaPos.X,
+ remoteClient.Scene.RegionInfo.WorldLocY + avaPos.Y,
avaPos.Z);
string landOwnerName = string.Empty;
@@ -1353,4 +1353,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
}
#endregion Web Util
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 6e0fd03419..f615c6b9e6 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -317,9 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework
foreach (KeyValuePair kvp in m_childrenSeeds[agentID])
{
uint x, y;
- Utils.LongToUInts(kvp.Key, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
}
}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index b32a169c97..c81e5aa6cf 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -121,8 +121,57 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
private EntityTransferStateMachine m_entityTransferStateMachine;
- private ExpiringCache> m_bannedRegions =
- new ExpiringCache>();
+ // For performance, we keed a cached of banned regions so we don't keep going
+ // to the grid service.
+ private class BannedRegionCache
+ {
+ private ExpiringCache> m_bannedRegions =
+ new ExpiringCache>();
+ ExpiringCache m_idCache;
+ DateTime m_banUntil;
+ public BannedRegionCache()
+ {
+ }
+ // Return 'true' if there is a valid ban entry for this agent in this region
+ public bool IfBanned(ulong pRegionHandle, UUID pAgentID)
+ {
+ bool ret = false;
+ if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
+ {
+ if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
+ {
+ if (DateTime.Now < m_banUntil)
+ {
+ ret = true;
+ }
+ }
+ }
+ return ret;
+ }
+ // Add this agent in this region as a banned person
+ public void Add(ulong pRegionHandle, UUID pAgentID)
+ {
+ this.Add(pRegionHandle, pAgentID, 45, 15);
+ }
+ public void Add(ulong pRegionHandle, UUID pAgentID, double newTime, double extendTime)
+ {
+ if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
+ {
+ m_idCache = new ExpiringCache();
+ m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime));
+ }
+ m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(extendTime), TimeSpan.FromSeconds(extendTime));
+ }
+ // Remove the agent from the region's banned list
+ public void Remove(ulong pRegionHandle, UUID pAgentID)
+ {
+ if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
+ {
+ m_idCache.Remove(pRegionHandle);
+ }
+ }
+ }
+ private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
private IEventQueue m_eqModule;
private IRegionCombinerModule m_regionCombinerModule;
@@ -337,6 +386,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name);
}
+ // Attempt to teleport the ScenePresence to the specified position in the specified region (spec'ed by its handle).
public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
{
if (sp.Scene.Permissions.IsGridGod(sp.UUID))
@@ -418,7 +468,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.Name, position, sp.Scene.RegionInfo.RegionName);
// Teleport within the same region
- if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
+ if (!sp.Scene.PositionIsInCurrentRegion(position) || position.Z < 0)
{
Vector3 emergencyPos = new Vector3(128, 128, 128);
@@ -437,10 +487,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
float posZLimit = 22;
// TODO: Check other Scene HeightField
- if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
- {
- posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
- }
+ posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
posZLimit += localHalfAVHeight + 0.1f;
@@ -484,9 +531,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
ScenePresence sp, ulong regionHandle, Vector3 position,
Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
{
- uint x = 0, y = 0;
- Utils.LongToUInts(regionHandle, out x, out y);
- GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
+ // Get destination region taking into account that the address could be an offset
+ // region inside a varregion.
+ GridRegion reg = GetTeleportDestinationRegion(sp.Scene.GridService, sp.Scene.RegionInfo.ScopeID, regionHandle, ref position);
if (reg != null)
{
@@ -537,12 +584,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// and set the map-tile to '(Offline)'
uint regX, regY;
- Utils.LongToUInts(regionHandle, out regX, out regY);
+ Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
MapBlockData block = new MapBlockData();
- block.X = (ushort)(regX / Constants.RegionSize);
- block.Y = (ushort)(regY / Constants.RegionSize);
- block.Access = 254; // == not there
+ block.X = (ushort)(regX);
+ block.Y = (ushort)(regY);
+ block.Access = (byte)SimAccess.Down; // == not there
List blocks = new List();
blocks.Add(block);
@@ -550,6 +597,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
+ // The teleport address could be an address in a subregion of a larger varregion.
+ // Find the real base region and adjust the teleport location to account for the
+ // larger region.
+ private GridRegion GetTeleportDestinationRegion(IGridService gridService, UUID scope, ulong regionHandle, ref Vector3 position)
+ {
+ uint x = 0, y = 0;
+ Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
+
+ // Compute the world location we're teleporting to
+ double worldX = (double)x + position.X;
+ double worldY = (double)y + position.Y;
+
+ // Find the region that contains the position
+ GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY);
+
+ if (reg != null)
+ {
+ // modify the position for the offset into the actual region returned
+ position.X += x - reg.RegionLocX;
+ position.Y += y - reg.RegionLocY;
+ }
+
+ return reg;
+ }
+
// Nothing to validate here
protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
{
@@ -650,10 +722,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return;
}
- uint newRegionX = (uint)(reg.RegionHandle >> 40);
- uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
- uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
- uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
+ uint newRegionX, newRegionY, oldRegionX, oldRegionY;
+ Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
+ Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
ulong destinationHandle = finalDestination.RegionHandle;
@@ -675,8 +746,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
string reason;
string version;
+ string myversion = string.Format("{0}/{1}", OutgoingTransferVersionName, MaxOutgoingTransferVersion);
if (!Scene.SimulationService.QueryAccess(
- finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
+ finalDestination, sp.ControllingClient.AgentId, position, out version, out reason))
{
sp.ControllingClient.SendTeleportFailed(reason);
@@ -1274,6 +1346,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return region;
}
+ // This returns 'true' if the new region already has a child agent for our
+ // incoming agent. The implication is that, if 'false', we have to create the
+ // child and then teleport into the region.
protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
{
if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
@@ -1298,20 +1373,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
}
- protected virtual bool IsOutsideRegion(Scene s, Vector3 pos)
- {
- if (s.TestBorderCross(pos, Cardinals.N))
- return true;
- if (s.TestBorderCross(pos, Cardinals.S))
- return true;
- if (s.TestBorderCross(pos, Cardinals.E))
- return true;
- if (s.TestBorderCross(pos, Cardinals.W))
- return true;
-
- return false;
- }
-
#endregion
#region Landmark Teleport
@@ -1398,42 +1459,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
UUID agentID = agent.UUID;
ulong destinyHandle = destiny.RegionHandle;
- ExpiringCache r;
- DateTime banUntil;
- if (m_bannedRegions.TryGetValue(agentID, out r))
+ if (m_bannedRegionCache.IfBanned(destinyHandle, agentID))
{
- if (r.TryGetValue(destinyHandle, out banUntil))
- {
- if (DateTime.Now < banUntil)
- {
- reason = "Cannot connect to region";
- return false;
- }
- r.Remove(destinyHandle);
- }
- }
- else
- {
- r = null;
+ reason = "Cannot connect to region";
+ return false;
}
Scene ascene = agent.Scene;
if (!ascene.SimulationService.QueryAccess(destiny, agentID, position, out version, out reason))
{
- if (r == null)
- {
- r = new ExpiringCache();
- r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
-
- m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(30));
- }
- else
- {
- r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
- }
+ m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
return false;
}
+
return true;
}
@@ -1443,161 +1482,74 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return GetDestination(scene, agentID, pos, out version, out newpos, out r);
}
- public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos, out string reason)
+ // Given a position relative to the current region (which has previously been tested to
+ // see that it is actually outside the current region), find the new region that the
+ // point is actually in.
+ // Returns the coordinates and information of the new region or 'null' of it doesn't exist.
+ public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos,
+ out string version, out Vector3 newpos, out string failureReason)
{
version = String.Empty;
- reason = String.Empty;
newpos = pos;
+ failureReason = string.Empty;
// m_log.DebugFormat(
// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
- RegionInfo regInfo = scene.RegionInfo;
+ // Compute world location of the object's position
+ double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
+ double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
- uint neighbourx = regInfo.RegionLocX;
- uint neighboury = regInfo.RegionLocY;
- const float boundaryDistance = 0.7f;
+ // Call the grid service to lookup the region containing the new position.
+ GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
+ presenceWorldX, presenceWorldY,
+ Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
-/*
- Vector3 northCross = new Vector3(0, boundaryDistance, 0);
- Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
- Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
- Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
-
- // distance into new region to place avatar
- const float enterDistance = 0.5f;
- const float maxX = Constants.RegionSize - enterDistance;
- const float maxY = Constants.RegionSize - enterDistance;
-
- if (scene.TestBorderCross(pos + westCross, Cardinals.W))
+ if (neighbourRegion != null)
{
- if (scene.TestBorderCross(pos + northCross, Cardinals.N))
+ // Compute the entity's position relative to the new region
+ newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
+ (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
+ pos.Z);
+
+ if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
{
- Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
+ failureReason = "Cannot region cross into banned parcel";
+ neighbourRegion = null;
}
- else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
+ else
{
- neighboury--;
- newpos.Y += Constants.RegionSize;
+ // If not banned, make sure this agent is not in the list.
+ m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
}
- neighbourx--;
- newpos.X += Constants.RegionSize;
- }
- else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
- {
- Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
- neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
- newpos.X -= Constants.RegionSize;
-
- if (scene.TestBorderCross(pos + southCross, Cardinals.S))
+ // Check to see if we have access to the target region.
+ string myversion = string.Format("{0}/{1}", OutgoingTransferVersionName, MaxOutgoingTransferVersion);
+ if (neighbourRegion != null
+ && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out failureReason))
{
- neighboury--;
- newpos.Y += Constants.RegionSize;
- }
- else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
- {
- Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
- }
- }
- else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
- {
- Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
- neighboury--;
- newpos.Y += Constants.RegionSize;
- }
- else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
- {
- Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
- }
-
- newpos.X = Util.Clamp(newpos.X, enterDistance, maxX);
- newpos.Y = Util.Clamp(newpos.Y, enterDistance, maxY);
-*/
- float regionSizeX = regInfo.RegionSizeX;
- float regionSizeY = regInfo.RegionSizeY;
-
- if (pos.X < boundaryDistance)
- neighbourx--;
- else if (pos.X > regionSizeX - boundaryDistance)
- neighbourx += (uint)(regionSizeX / Constants.RegionSize);
-
- if (pos.Y < boundaryDistance)
- neighboury--;
- else if (pos.Y > regionSizeY - boundaryDistance)
- neighboury += (uint)(regionSizeY / Constants.RegionSize);
-
- int x = (int)(neighbourx * Constants.RegionSize);
- int y = (int)(neighboury * Constants.RegionSize);
-
- ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y);
-
- ExpiringCache r;
- DateTime banUntil;
-
- if (m_bannedRegions.TryGetValue(agentID, out r))
- {
- if (r.TryGetValue(neighbourHandle, out banUntil))
- {
- if (DateTime.Now < banUntil)
- return null;
- r.Remove(neighbourHandle);
+ // remember banned
+ m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
+ neighbourRegion = null;
}
}
else
{
- r = null;
+ // The destination region just doesn't exist
+ failureReason = "Cannot cross into non-existent region";
}
- GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
if (neighbourRegion == null)
- {
- reason = "";
- return null;
- }
-
- float newRegionSizeX = neighbourRegion.RegionSizeX;
- float newRegionSizeY = neighbourRegion.RegionSizeY;
- if (newRegionSizeX == 0)
- newRegionSizeX = Constants.RegionSize;
- if (newRegionSizeY == 0)
- newRegionSizeY = Constants.RegionSize;
-
- if (pos.X < boundaryDistance)
- newpos.X += newRegionSizeX;
- else if (pos.X > regionSizeX - boundaryDistance)
- newpos.X -= regionSizeX;
-
- if (pos.Y < boundaryDistance)
- newpos.Y += newRegionSizeY;
- else if (pos.Y > regionSizeY - boundaryDistance)
- newpos.Y -= regionSizeY;
-
- const float enterDistance = 0.5f;
- newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
- newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
-
- if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
- {
- if (r == null)
- {
- r = new ExpiringCache();
- r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
-
- m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45));
- }
- else
- {
- r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
- }
- return null;
- }
+ m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
+ LogHeader, scene.RegionInfo.RegionName,
+ scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
+ scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
+ pos);
+ else
+ m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
+ LogHeader, neighbourRegion.RegionName,
+ neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
+ newpos.X, newpos.Y);
return neighbourRegion;
}
@@ -1632,15 +1584,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
uint y;
Vector3 newpos;
string version;
- string reason;
+ string failureReason;
Vector3 pos = agent.AbsolutePosition + agent.Velocity;
- GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos, out version, out newpos, out reason);
+ GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos,
+ out version, out newpos, out failureReason);
if (neighbourRegion == null)
{
- if (reason != String.Empty)
- agent.ControllingClient.SendAlertMessage("Cannot cross to region");
+ if (failureReason != String.Empty)
+ agent.ControllingClient.SendAlertMessage(failureReason);
return agent;
}
@@ -1678,7 +1631,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agent.Scene.RequestTeleportLocation(
agent.ControllingClient,
- Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize),
+ Util.RegionLocToHandle(regionX, regionY),
position,
agent.Lookat,
(uint)Constants.TeleportFlags.ViaLocation);
@@ -1688,11 +1641,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (im != null)
{
UUID gotoLocation = Util.BuildFakeParcelID(
- Util.UIntsToLong(
- (regionX *
- (uint)Constants.RegionSize),
- (regionY *
- (uint)Constants.RegionSize)),
+ Util.RegionLocToHandle(regionX, regionY),
(uint)(int)position.X,
(uint)(int)position.Y,
(uint)(int)position.Z);
@@ -1745,8 +1694,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
///
public ScenePresence CrossAgentToNewRegionAsync(
- ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
- bool isFlying, string version)
+ ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
+ bool isFlying, string version)
{
if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
{
@@ -1893,11 +1842,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Next, let's close the child agent connections that are too far away.
uint neighbourx;
uint neighboury;
-
- Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
-
- neighbourx /= Constants.RegionSize;
- neighboury /= Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
agent.CloseChildAgents(neighbourx, neighboury);
@@ -2059,7 +2004,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (m_regionInfo != null)
{
- neighbours = RequestNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
+ neighbours = GetNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
}
else
{
@@ -2216,15 +2161,195 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
+ // Computes the difference between two region bases.
+ // Returns a vector of world coordinates (meters) from base of first region to the second.
+ // The first region is the home region of the passed scene presence.
Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
{
- int rRegionX = (int)sp.Scene.RegionInfo.RegionLocX;
- int rRegionY = (int)sp.Scene.RegionInfo.RegionLocY;
+ /*
+ int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
+ int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
return new Vector3(shiftx, shifty, 0f);
+ */
+ return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
+ sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
+ 0f);
+ }
+
+ public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
+ {
+ // Since we don't know how big the regions could be, we have to search a very large area
+ // to find possible regions.
+ return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
+ }
+
+ #region NotFoundLocationCache class
+ // A collection of not found locations to make future lookups 'not found' lookups quick.
+ // A simple expiring cache that keeps not found locations for some number of seconds.
+ // A 'not found' location is presumed to be anywhere in the minimum sized region that
+ // contains that point. A conservitive estimate.
+ private class NotFoundLocationCache
+ {
+ private struct NotFoundLocation
+ {
+ public double minX, maxX, minY, maxY;
+ public DateTime expireTime;
+ }
+ private List m_notFoundLocations = new List();
+ public NotFoundLocationCache()
+ {
+ }
+ // Add an area to the list of 'not found' places. The area is the snapped region
+ // area around the added point.
+ public void Add(double pX, double pY)
+ {
+ lock (m_notFoundLocations)
+ {
+ if (!LockedContains(pX, pY))
+ {
+ NotFoundLocation nfl = new NotFoundLocation();
+ // A not found location is not found for at least a whole region sized area
+ nfl.minX = pX - (pX % (double)Constants.RegionSize);
+ nfl.minY = pY - (pY % (double)Constants.RegionSize);
+ nfl.maxX = nfl.minX + (double)Constants.RegionSize;
+ nfl.maxY = nfl.minY + (double)Constants.RegionSize;
+ nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
+ m_notFoundLocations.Add(nfl);
+ }
+ }
+
+ }
+ // Test to see of this point is in any of the 'not found' areas.
+ // Return 'true' if the point is found inside the 'not found' areas.
+ public bool Contains(double pX, double pY)
+ {
+ bool ret = false;
+ lock (m_notFoundLocations)
+ ret = LockedContains(pX, pY);
+ return ret;
+ }
+ private bool LockedContains(double pX, double pY)
+ {
+ bool ret = false;
+ this.DoExpiration();
+ foreach (NotFoundLocation nfl in m_notFoundLocations)
+ {
+ if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY)
+ {
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+ }
+ private void DoExpiration()
+ {
+ List m_toRemove = null;
+ DateTime now = DateTime.Now;
+ foreach (NotFoundLocation nfl in m_notFoundLocations)
+ {
+ if (nfl.expireTime < now)
+ {
+ if (m_toRemove == null)
+ m_toRemove = new List();
+ m_toRemove.Add(nfl);
+ }
+ }
+ if (m_toRemove != null)
+ {
+ foreach (NotFoundLocation nfl in m_toRemove)
+ m_notFoundLocations.Remove(nfl);
+ m_toRemove.Clear();
+ }
+ }
+ }
+ #endregion // NotFoundLocationCache class
+ private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
+
+ // Given a world position (fractional meter coordinate), get the GridRegion info for
+ // the region containing that point.
+ // Someday this should be a method on GridService.
+ // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
+ // the size of the target region is unknown thus the search area might have to be very large.
+ // Return 'null' if no such region exists.
+ public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
+ double px, double py, uint pSizeHint)
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
+ GridRegion ret = null;
+ const double fudge = 2.0;
+
+ // One problem with this routine is negative results. That is, this can be called lots of times
+ // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
+ // will be quick 'not found's next time.
+ // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
+ // thus re-ask the GridService about the location.
+ if (m_notFoundLocationCache.Contains(px, py))
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
+ return null;
+ }
+
+ // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
+ // the region at the appropriate legacy region location.
+ uint possibleX = (uint)Math.Floor(px);
+ possibleX -= possibleX % Constants.RegionSize;
+ uint possibleY = (uint)Math.Floor(py);
+ possibleY -= possibleY % Constants.RegionSize;
+ ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
+ if (ret != null)
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
+ LogHeader, possibleX, possibleY, ret.RegionName);
+ }
+
+ if (ret == null)
+ {
+ // If the simple lookup failed, search the larger area for a region that contains this point
+ double range = (double)pSizeHint + fudge;
+ while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
+ {
+ // Get from the grid service a list of regions that might contain this point.
+ // The region origin will be in the zero direction so only subtract the range.
+ List possibleRegions = pGridService.GetRegionRange(pScopeID,
+ (int)(px - range), (int)(px),
+ (int)(py - range), (int)(py));
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
+ LogHeader, possibleRegions.Count, range);
+ if (possibleRegions != null && possibleRegions.Count > 0)
+ {
+ // If we found some regions, check to see if the point is within
+ foreach (GridRegion gr in possibleRegions)
+ {
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
+ LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
+ if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
+ && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
+ {
+ // Found a region that contains the point
+ ret = gr;
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
+ break;
+ }
+ }
+ }
+ // Larger search area for next time around if not found
+ range *= 2;
+ }
+ }
+
+ if (ret == null)
+ {
+ // remember this location was not found so we can quickly not find it next time
+ m_notFoundLocationCache.Add(px, py);
+ m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
+ }
+
+ return ret;
}
private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2310,22 +2435,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
{
- Border[] northBorders = Scene.NorthBorders.ToArray();
- Border[] eastBorders = Scene.EastBorders.ToArray();
-
Vector2 extent = Vector2.Zero;
- for (int i = 0; i < eastBorders.Length; i++)
+
+ if (m_regionCombinerModule != null)
{
- extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
- }
- for (int i = 0; i < northBorders.Length; i++)
- {
- extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
+ Vector2 megaRegionSize = m_regionCombinerModule.GetSizeOfMegaregion(Scene.RegionInfo.RegionID);
+ extent.X = (float)Util.WorldToRegionLoc((uint)megaRegionSize.X);
+ extent.Y = (float)Util.WorldToRegionLoc((uint)megaRegionSize.Y);
}
- // Loss of fraction on purpose
- extent.X = ((int)extent.X / (int)Constants.RegionSize);
- extent.Y = ((int)extent.Y / (int)Constants.RegionSize);
swCorner.X = Scene.RegionInfo.RegionLocX - 1;
swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
@@ -2340,56 +2458,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
///
///
- protected List RequestNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
+ protected List GetNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
{
Scene pScene = avatar.Scene;
RegionInfo m_regionInfo = pScene.RegionInfo;
+ List neighbours;
// Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't
// clear what should be done with a "far view" given that megaregions already extended the
// view to include everything in the megaregion
if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
{
- int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance;
+ // The area to check is as big as the current region.
+ // We presume all adjacent regions are the same size as this region.
+ uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
+ Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
- dd--;
+ uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;
+ uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2;
- // region center
- int endX = (int)pRegionLocX * (int)Constants.RegionSize + (int)(Constants.RegionSize / 2);
- int endY = (int)pRegionLocY * (int)Constants.RegionSize + (int)(Constants.RegionSize / 2);
-
- int startX = endX - dd;
- int startY = endY - dd;
+ uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2;
+ uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2;
- endX += dd;
- endY += dd;
+ neighbours
+ = avatar.Scene.GridService.GetRegionRange(
+ m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
- if (startX < 0) startX = 0;
- if (startY < 0) startY = 0;
-
- List neighbours =
- avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
-
- neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
- return neighbours;
}
else
{
Vector2 swCorner, neCorner;
GetMegaregionViewRange(out swCorner, out neCorner);
- List neighbours
+ neighbours
= pScene.GridService.GetRegionRange(
m_regionInfo.ScopeID,
- (int)swCorner.X * (int)Constants.RegionSize,
- (int)neCorner.X * (int)Constants.RegionSize,
- (int)swCorner.Y * (int)Constants.RegionSize,
- (int)neCorner.Y * (int)Constants.RegionSize);
-
- neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
-
- return neighbours;
+ (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
+ (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
}
+
+ // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1).
+ neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
+
+ return neighbours;
}
/* not in use
private List NewNeighbours(List currentNeighbours, List previousNeighbours)
@@ -2509,8 +2620,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
///
/// This method locates the new region handle and offsets the prim position for the new region
///
- /// the attempted out of region position of the scene object
/// the scene object that we're crossing
+ /// the attempted out of region position of the scene object. This position is
+ /// relative to the region the object currently is in.
+ /// if 'true', the deletion of the client from the region is not broadcast to the clients
public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
{
if (grp == null)
@@ -2522,209 +2635,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (scene == null)
return;
-
- int thisx = (int)scene.RegionInfo.RegionLocX;
- int thisy = (int)scene.RegionInfo.RegionLocY;
- Vector3 EastCross = new Vector3(0.1f, 0, 0);
- Vector3 WestCross = new Vector3(-0.1f, 0, 0);
- Vector3 NorthCross = new Vector3(0, 0.1f, 0);
- Vector3 SouthCross = new Vector3(0, -0.1f, 0);
-
-
- // use this if no borders were crossed!
- ulong newRegionHandle
- = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize),
- (uint)((thisy) * Constants.RegionSize));
-
- Vector3 pos = attemptedPosition;
-
- int changeX = 1;
- int changeY = 1;
-
- if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W))
- {
- if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
- {
-
- Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
-
- if (crossedBorderx.BorderLine.Z > 0)
- {
- pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
- changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.X = ((pos.X + Constants.RegionSize));
-
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
-
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
- (uint)((thisy - changeY) * Constants.RegionSize));
- // x - 1
- // y - 1
- }
- else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
- {
- Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
-
- if (crossedBorderx.BorderLine.Z > 0)
- {
- pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
- changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.X = ((pos.X + Constants.RegionSize));
-
-
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
- (uint)((thisy + changeY) * Constants.RegionSize));
- // x - 1
- // y + 1
- }
- else
- {
- Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
-
- if (crossedBorderx.BorderLine.Z > 0)
- {
- pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
- changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.X = ((pos.X + Constants.RegionSize));
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
- (uint)(thisy * Constants.RegionSize));
- // x - 1
- }
- }
- else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
- {
- if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
- {
-
- pos.X = ((pos.X - Constants.RegionSize));
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
-
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
- (uint)((thisy - changeY) * Constants.RegionSize));
- // x + 1
- // y - 1
- }
- else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
- {
- pos.X = ((pos.X - Constants.RegionSize));
- pos.Y = ((pos.Y - Constants.RegionSize));
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
- (uint)((thisy + changeY) * Constants.RegionSize));
- // x + 1
- // y + 1
- }
- else
- {
- pos.X = ((pos.X - Constants.RegionSize));
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
- (uint)(thisy * Constants.RegionSize));
- // x + 1
- }
- }
- else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
- {
- Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
- //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
-
- if (crossedBordery.BorderLine.Z > 0)
- {
- pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
- changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
- }
- else
- pos.Y = ((pos.Y + Constants.RegionSize));
-
- newRegionHandle
- = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize));
- // y - 1
- }
- else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
- {
-
- pos.Y = ((pos.Y - Constants.RegionSize));
- newRegionHandle
- = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize));
- // y + 1
- }
-
- // Offset the positions for the new region across the border
+ // Remember the old group position in case the region lookup fails so position can be restored.
Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
- // If we fail to cross the border, then reset the position of the scene object on that border.
- uint x = 0, y = 0;
- Utils.LongToUInts(newRegionHandle, out x, out y);
- GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
+ // Compute the absolute position of the object.
+ double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X;
+ double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y;
+ // Ask the grid service for the region that contains the passed address
+ GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
+ objectWorldLocX, objectWorldLocY);
+
+ Vector3 pos = Vector3.Zero;
if (destination != null)
{
- if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
- return; // we did it
+ // Adjust the object's relative position from the old region (attemptedPosition)
+ // to be relative to the new region (pos).
+ pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
+ (float)(objectWorldLocY - (double)destination.RegionLocY),
+ attemptedPosition.Z);
}
- // no one or failed lets go back and tell physics to go on
- oldGroupPosition.X = Util.Clamp(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
- oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
-// oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z, 0.5f, 4096.0f);
+ if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
+ {
+ m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID);
- grp.AbsolutePosition = oldGroupPosition;
- grp.Velocity = Vector3.Zero;
+ // We are going to move the object back to the old position so long as the old position
+ // is in the region
+ oldGroupPosition.X = Util.Clamp(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
+ oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
+ oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
- if (grp.RootPart.PhysActor != null)
- grp.RootPart.PhysActor.CrossingFailure();
+ grp.AbsolutePosition = oldGroupPosition;
+ grp.Velocity = Vector3.Zero;
+ if (grp.RootPart.PhysActor != null)
+ grp.RootPart.PhysActor.CrossingFailure();
- if (grp.RootPart.KeyframeMotion != null)
- grp.RootPart.KeyframeMotion.CrossingFailure();
+ if (grp.RootPart.KeyframeMotion != null)
+ grp.RootPart.KeyframeMotion.CrossingFailure();
- grp.ScheduleGroupForFullUpdate();
+ grp.ScheduleGroupForFullUpdate();
+ }
}
-
-
///
/// Move the given scene object into a new region
///
diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
index d943b20a2a..4e7ad7546a 100644
--- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
@@ -213,8 +213,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
if (part != null)
{
ObjectRegionName = s.RegionInfo.RegionName;
- uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize);
- uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize);
+ uint localX = s.RegionInfo.WorldLocX;
+ uint localY = s.RegionInfo.WorldLocY;
ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")";
return part;
}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 31ef79baf4..8ccad399e1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -268,11 +268,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
List regions = kvp.Value.GetNeighbours();
foreach (GridRegion r in regions)
- caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
+ caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
}
}
MainConsole.Instance.Output(caps.ToString());
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
index 9172536742..ae7628859f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return;
m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}",
- m_scene.RegionInfo.RegionName, otherRegion.RegionName, otherRegion.RegionLocX / Constants.RegionSize, otherRegion.RegionLocY / Constants.RegionSize);
+ m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY));
m_neighbours[otherRegion.RegionHandle] = otherRegion;
}
@@ -82,11 +82,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
return new List(m_neighbours.Values);
}
+ // Get a region given its base coordinates (in meters).
+ // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
+ // be the base coordinate of the region.
+ // The snapping is technically unnecessary but is harmless because regions are always
+ // multiples of the legacy region size (256).
public GridRegion GetRegionByPosition(int x, int y)
{
uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize;
uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize;
- ulong handle = Utils.UIntsToLong(xsnap, ysnap);
+ ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap);
if (m_neighbours.ContainsKey(handle))
return m_neighbours[handle];
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index 43381337c7..6a49ca7b1d 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
Assert.IsNotNull(result, "Retrieved GetRegionByUUID is null");
Assert.That(result.RegionID, Is.EqualTo(new UUID(1)), "Retrieved region's UUID does not match");
- result = m_LocalConnector.GetRegionByPosition(UUID.Zero, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize);
+ result = m_LocalConnector.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000));
Assert.IsNotNull(result, "Retrieved GetRegionByPosition is null");
Assert.That(result.RegionLocX, Is.EqualTo(1000 * (int)Constants.RegionSize), "Retrieved region's position does not match");
@@ -197,4 +197,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected");
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 96182cdcb1..da74f30dee 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static string LogHeader = "[MAP IMAGE SERVICE MODULE]";
private bool m_enabled = false;
private IMapImageService m_MapService;
@@ -192,47 +193,94 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
m_lastrefresh = Util.EnvironmentTickCount();
}
+ public void UploadMapTile(IScene scene, Bitmap mapTile)
+ {
+ m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.Name);
+
+ // mapTile.Save( // DEBUG DEBUG
+ // String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY),
+ // ImageFormat.Jpeg);
+ // If the region/maptile is legacy sized, just upload the one tile like it has always been done
+ if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
+ {
+ ConvertAndUploadMaptile(mapTile, scene,
+ scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY);
+ }
+ else
+ {
+ // For larger regions (varregion) we must cut the region image into legacy sized
+ // pieces since that is how the maptile system works.
+ // Note the assumption that varregions are always a multiple of legacy size.
+ for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize)
+ {
+ for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize)
+ {
+ // Images are addressed from the upper left corner so have to do funny
+ // math to pick out the sub-tile since regions are numbered from
+ // the lower left.
+ Rectangle rect = new Rectangle(
+ (int)xx,
+ mapTile.Height - (int)yy - (int)Constants.RegionSize,
+ (int)Constants.RegionSize, (int)Constants.RegionSize);
+ using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
+ {
+ ConvertAndUploadMaptile(subMapTile, scene,
+ scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize),
+ scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize)
+ );
+ }
+ }
+ }
+ }
+ }
+
///
///
///
public void UploadMapTile(IScene scene)
{
- m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName);
+ m_log.DebugFormat("{0}: upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName);
// Create a JPG map tile and upload it to the AddMapTile API
- byte[] jpgData = Utils.EmptyBytes;
IMapImageGenerator tileGenerator = scene.RequestModuleInterface();
if (tileGenerator == null)
{
- m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator");
+ m_log.WarnFormat("{0} Cannot upload map tile without an ImageGenerator", LogHeader);
return;
}
- using (Image mapTile = tileGenerator.CreateMapTile())
+ using (Bitmap mapTile = tileGenerator.CreateMapTile())
{
// XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
// is no static map tile.
if (mapTile == null)
return;
- using (MemoryStream stream = new MemoryStream())
+ UploadMapTile(scene, mapTile);
+ }
+ }
+
+ private void ConvertAndUploadMaptile(Image tileImage, IScene scene, uint locX, uint locY)
+ {
+ byte[] jpgData = Utils.EmptyBytes;
+
+ using (MemoryStream stream = new MemoryStream())
+ {
+ tileImage.Save(stream, ImageFormat.Jpeg);
+ jpgData = stream.ToArray();
+ }
+ if (jpgData != Utils.EmptyBytes)
+ {
+ string reason = string.Empty;
+ if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, scene.RegionInfo.ScopeID, out reason))
{
- mapTile.Save(stream, ImageFormat.Jpeg);
- jpgData = stream.ToArray();
+ m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
+ scene.RegionInfo.RegionName, locX, locY, reason);
}
}
-
- if (jpgData == Utils.EmptyBytes)
+ else
{
- m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed");
- return;
- }
-
- string reason = string.Empty;
- if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, scene.RegionInfo.ScopeID, out reason))
- {
- m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}",
- scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason);
+ m_log.WarnFormat("{0} Tile image generation failed for region {1}", LogHeader, scene.RegionInfo.RegionName);
}
}
}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
index fd89428c8c..bda354fd94 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
@@ -125,14 +125,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
public OpenSim.Services.Interfaces.GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion)
{
uint x, y;
- Utils.LongToUInts(regionHandle, out x, out y);
+ Util.RegionHandleToRegionLoc(regionHandle, out x, out y);
foreach (Scene s in m_Scenes)
{
if (s.RegionInfo.RegionHandle == regionHandle)
{
m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
- thisRegion.RegionName, s.Name, x / Constants.RegionSize, y / Constants.RegionSize);
+ thisRegion.RegionName, s.Name, x, y );
//m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour");
return s.IncomingHelloNeighbour(thisRegion);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index 7a844f49f4..cd95ee9784 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -533,7 +533,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (isMegaregion)
size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
else
- size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
+ size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 92790664ce..4aee6a52c8 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -64,6 +64,12 @@ namespace OpenSim.Region.CoreModules.World.Land
public class LandManagementModule : INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
+
+ ///
+ /// Minimum land unit size in region co-ordinates.
+ ///
+ public const int landUnit = 4;
private static readonly string remoteParcelRequestPath = "0009/";
@@ -74,15 +80,10 @@ namespace OpenSim.Region.CoreModules.World.Land
protected IPrimCountModule m_primCountModule;
protected IDialogModule m_Dialog;
- // Minimum for parcels to work is 64m even if we don't actually use them.
- #pragma warning disable 0429
- private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
- #pragma warning restore 0429
-
///
/// Local land ids at specified region co-ordinates (region size / 4)
///
- private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax];
+ private int[,] m_landIDList;
///
/// Land objects keyed by local id
@@ -123,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Land
public void AddRegion(Scene scene)
{
m_scene = scene;
- m_landIDList.Initialize();
+ m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
landChannel = new LandChannel(scene, this);
parcelInfoCache = new Cache();
@@ -235,7 +236,7 @@ namespace OpenSim.Region.CoreModules.World.Land
public void UpdateLandObject(int local_id, LandData data)
{
LandData newData = data.Copy();
- newData.LocalID = local_id;
+ newData.LocalID = local_id;
ILandObject land;
lock (m_landList)
@@ -264,7 +265,7 @@ namespace OpenSim.Region.CoreModules.World.Land
{
m_landList.Clear();
m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
- m_landIDList.Initialize();
+ m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
}
}
@@ -274,11 +275,11 @@ namespace OpenSim.Region.CoreModules.World.Land
/// The parcel created.
protected ILandObject CreateDefaultParcel()
{
- m_log.DebugFormat(
- "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
+ m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName);
ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
- fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
+ fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
+ (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
@@ -569,9 +570,9 @@ namespace OpenSim.Region.CoreModules.World.Land
new_land.LandData.LocalID = newLandLocalID;
bool[,] landBitmap = new_land.GetLandBitmap();
- for (int x = 0; x < landArrayMax; x++)
+ for (int x = 0; x < landBitmap.GetLength(0); x++)
{
- for (int y = 0; y < landArrayMax; y++)
+ for (int y = 0; y < landBitmap.GetLength(1); y++)
{
if (landBitmap[x, y])
{
@@ -601,9 +602,9 @@ namespace OpenSim.Region.CoreModules.World.Land
ILandObject land;
lock (m_landList)
{
- for (int x = 0; x < 64; x++)
+ for (int x = 0; x < m_landIDList.GetLength(0); x++)
{
- for (int y = 0; y < 64; y++)
+ for (int y = 0; y < m_landIDList.GetLength(1); y++)
{
if (m_landIDList[x, y] == local_id)
{
@@ -656,9 +657,9 @@ namespace OpenSim.Region.CoreModules.World.Land
bool[,] landBitmapSlave = slave.GetLandBitmap();
lock (m_landList)
{
- for (int x = 0; x < 64; x++)
+ for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
{
- for (int y = 0; y < 64; y++)
+ for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
{
if (landBitmapSlave[x, y])
{
@@ -695,20 +696,23 @@ namespace OpenSim.Region.CoreModules.World.Land
int x;
int y;
- if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0)
+ if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
return null;
try
{
- x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0));
- y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0));
+ x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
+ y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
}
catch (OverflowException)
{
return null;
}
- if (x >= 64 || y >= 64 || x < 0 || y < 0)
+ if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
+ || y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
+ || x < 0
+ || y < 0)
{
return null;
}
@@ -740,20 +744,20 @@ namespace OpenSim.Region.CoreModules.World.Land
int avx = (int)x;
if (avx < 0)
avx = 0;
- else if (avx >= (int)Constants.RegionSize)
+ else if (avx >= m_scene.RegionInfo.RegionSizeX)
avx = (int)Constants.RegionSize - 1;
int avy = (int)y;
if (avy < 0)
avy = 0;
- else if (avy >= (int)Constants.RegionSize)
+ else if (avy >= m_scene.RegionInfo.RegionSizeY)
avy = (int)Constants.RegionSize - 1;
lock (m_landIDList)
{
try
{
- return m_landList[m_landIDList[avx / 4, avy / 4]];
+ return m_landList[m_landIDList[avx / landUnit, avy / landUnit]];
}
catch (IndexOutOfRangeException)
{
@@ -764,7 +768,7 @@ namespace OpenSim.Region.CoreModules.World.Land
public ILandObject GetLandObject(int x, int y)
{
- if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0)
+ if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
{
// These exceptions here will cause a lot of complaints from the users specifically because
// they happen every time at border crossings
@@ -1057,9 +1061,10 @@ namespace OpenSim.Region.CoreModules.World.Land
int byteArrayCount = 0;
int sequenceID = 0;
- for (int y = 0; y < Constants.RegionSize; y += 4)
+ // Layer data is in landUnit (4m) chunks
+ for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += landUnit)
{
- for (int x = 0; x < Constants.RegionSize; x += 4)
+ for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += landUnit)
{
byte tempByte = 0; //This represents the byte for the current 4x4
@@ -1769,7 +1774,7 @@ namespace OpenSim.Region.CoreModules.World.Land
{
// most likely still cached from building the extLandData entry
uint x = 0, y = 0;
- Utils.LongToUInts(data.RegionHandle, out x, out y);
+ Util.RegionHandleToWorldLoc(data.RegionHandle, out x, out y);
info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
}
// we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index a3cd4a5673..5858d6c9ad 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -45,15 +45,13 @@ namespace OpenSim.Region.CoreModules.World.Land
#region Member Variables
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- #pragma warning disable 0429
- private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
- #pragma warning restore 0429
- private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax];
+ private static readonly string LogHeader = "[LAND OBJECT]";
+
+ private readonly int landUnit = 4;
private int m_lastSeqId = 0;
private int m_expiryCounter = 0;
- protected LandData m_landData = new LandData();
protected Scene m_scene;
protected List primsOverMe = new List();
protected Dictionary m_listTransactions = new Dictionary();
@@ -61,6 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Land
protected ExpiringCache m_groupMemberCache = new ExpiringCache();
protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
+ private bool[,] m_landBitmap;
public bool[,] LandBitmap
{
get { return m_landBitmap; }
@@ -76,6 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Land
return free;
}
+ protected LandData m_landData;
public LandData LandData
{
get { return m_landData; }
@@ -94,12 +94,12 @@ namespace OpenSim.Region.CoreModules.World.Land
{
get
{
- for (int y = 0; y < landArrayMax; y++)
+ for (int y = 0; y < LandBitmap.GetLength(1); y++)
{
- for (int x = 0; x < landArrayMax; x++)
+ for (int x = 0; x < LandBitmap.GetLength(0); x++)
{
if (LandBitmap[x, y])
- return new Vector3(x * 4, y * 4, 0);
+ return new Vector3(x * landUnit, y * landUnit, 0);
}
}
@@ -111,13 +111,13 @@ namespace OpenSim.Region.CoreModules.World.Land
{
get
{
- for (int y = landArrayMax - 1; y >= 0; y--)
+ for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
{
- for (int x = landArrayMax - 1; x >= 0; x--)
+ for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
{
if (LandBitmap[x, y])
{
- return new Vector3(x * 4 + 4, y * 4 + 4, 0);
+ return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
}
}
}
@@ -128,9 +128,21 @@ namespace OpenSim.Region.CoreModules.World.Land
#region Constructors
+ public LandObject(LandData landData, Scene scene)
+ {
+ LandData = landData.Copy();
+ m_scene = scene;
+ }
+
public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
{
m_scene = scene;
+ if (m_scene == null)
+ LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
+ else
+ LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
+
+ LandData = new LandData();
LandData.OwnerID = owner_id;
if (is_group_owned)
LandData.GroupID = owner_id;
@@ -155,9 +167,9 @@ namespace OpenSim.Region.CoreModules.World.Land
/// Returns true if the piece of land contains the specified point
public bool ContainsPoint(int x, int y)
{
- if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize)
+ if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
{
- return (LandBitmap[x / 4, y / 4] == true);
+ return LandBitmap[x / landUnit, y / landUnit];
}
else
{
@@ -197,10 +209,10 @@ namespace OpenSim.Region.CoreModules.World.Land
else
{
// Normal Calculations
- int parcelMax = (int)((long)LandData.Area
+ int parcelMax = (int)( (long)LandData.Area
* (long)m_scene.RegionInfo.ObjectCapacity
* (long)m_scene.RegionInfo.RegionSettings.ObjectBonus
- / 65536L);
+ / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
//m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
return parcelMax;
}
@@ -231,8 +243,9 @@ namespace OpenSim.Region.CoreModules.World.Land
else
{
//Normal Calculations
- int simMax = (int)((long)LandData.SimwideArea
- * (long)m_scene.RegionInfo.ObjectCapacity / 65536L);
+ int simMax = (int)( (long)LandData.SimwideArea
+ * (long)m_scene.RegionInfo.ObjectCapacity
+ / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
// m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax);
return simMax;
}
@@ -597,8 +610,8 @@ namespace OpenSim.Region.CoreModules.World.Land
try
{
over =
- m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)),
- Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1)));
+ m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
+ Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
}
catch (Exception)
{
@@ -752,9 +765,9 @@ namespace OpenSim.Region.CoreModules.World.Land
int max_y = Int32.MinValue;
int tempArea = 0;
int x, y;
- for (x = 0; x < 64; x++)
+ for (x = 0; x < LandBitmap.GetLength(0); x++)
{
- for (y = 0; y < 64; y++)
+ for (y = 0; y < LandBitmap.GetLength(1); y++)
{
if (LandBitmap[x, y] == true)
{
@@ -766,23 +779,25 @@ namespace OpenSim.Region.CoreModules.World.Land
max_x = x;
if (max_y < y)
max_y = y;
- tempArea += 16; //16sqm peice of land
+ tempArea += landUnit * landUnit; //16sqm peice of land
}
}
}
+ int tx = min_x * landUnit;
+ if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
+ tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
- int tx = min_x * 4;
int htx;
- if (tx == ((int)Constants.RegionSize))
- htx = tx - 1;
+ if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
+ htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
else
htx = tx;
- int ty = min_y * 4;
+ int ty = min_y * landUnit;
int hty;
- if (ty == ((int)Constants.RegionSize))
- hty = ty - 1;
+ if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
+ hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
else
hty = ty;
@@ -791,17 +806,17 @@ namespace OpenSim.Region.CoreModules.World.Land
(float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
max_x++;
- tx = max_x * 4;
- if (tx == ((int)Constants.RegionSize))
- htx = tx - 1;
+ tx = max_x * landUnit;
+ if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
+ htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
else
htx = tx;
max_y++;
ty = max_y * 4;
- if (ty == ((int)Constants.RegionSize))
- hty = ty - 1;
+ if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
+ hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
else
hty = ty;
@@ -819,20 +834,11 @@ namespace OpenSim.Region.CoreModules.World.Land
///
/// Sets the land's bitmap manually
///
- /// 64x64 block representing where this land is on a map
+ /// block representing where this land is on a map mapped in a 4x4 meter grid
public void SetLandBitmap(bool[,] bitmap)
{
- if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
- {
- //Throw an exception - The bitmap is not 64x64
- //throw new Exception("Error: Invalid Parcel Bitmap");
- }
- else
- {
- //Valid: Lets set it
- LandBitmap = bitmap;
- ForceUpdateLandInfo();
- }
+ LandBitmap = bitmap;
+ ForceUpdateLandInfo();
}
///
@@ -846,14 +852,16 @@ namespace OpenSim.Region.CoreModules.World.Land
public bool[,] BasicFullRegionLandBitmap()
{
- return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize);
+ return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
}
public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
{
- bool[,] tempBitmap = new bool[64,64];
+ // Empty bitmap for the whole region
+ bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
tempBitmap.Initialize();
+ // Fill the bitmap square area specified by state and end
tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
return tempBitmap;
}
@@ -871,19 +879,13 @@ namespace OpenSim.Region.CoreModules.World.Land
public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
bool set_value)
{
- if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
- {
- //Throw an exception - The bitmap is not 64x64
- //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
- }
-
int x, y;
- for (y = 0; y < 64; y++)
+ for (y = 0; y < land_bitmap.GetLength(1); y++)
{
- for (x = 0; x < 64; x++)
+ for (x = 0; x < land_bitmap.GetLength(0); x++)
{
- if (x >= start_x / 4 && x < end_x / 4
- && y >= start_y / 4 && y < end_y / 4)
+ if (x >= start_x / landUnit && x < end_x / landUnit
+ && y >= start_y / landUnit && y < end_y / landUnit)
{
land_bitmap[x, y] = set_value;
}
@@ -900,21 +902,21 @@ namespace OpenSim.Region.CoreModules.World.Land
///
public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
{
- if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
+ if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
+ || bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
+ || bitmap_add.Rank != 2
+ || bitmap_base.Rank != 2)
{
- //Throw an exception - The bitmap is not 64x64
- throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps");
- }
- if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
- {
- //Throw an exception - The bitmap is not 64x64
- throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
+ throw new Exception(
+ String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
+ LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
+ );
}
int x, y;
- for (y = 0; y < 64; y++)
+ for (y = 0; y < bitmap_base.GetLength(1); y++)
{
- for (x = 0; x < 64; x++)
+ for (x = 0; x < bitmap_add.GetLength(0); x++)
{
if (bitmap_add[x, y])
{
@@ -931,14 +933,14 @@ namespace OpenSim.Region.CoreModules.World.Land
///
private byte[] ConvertLandBitmapToBytes()
{
- byte[] tempConvertArr = new byte[512];
+ byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
int tempByte = 0;
- int x, y, i, byteNum = 0;
+ int i, byteNum = 0;
int mask = 1;
i = 0;
- for (y = 0; y < 64; y++)
+ for (int y = 0; y < LandBitmap.GetLength(1); y++)
{
- for (x = 0; x < 64; x++)
+ for (int x = 0; x < LandBitmap.GetLength(0); x++)
{
if (LandBitmap[x, y])
tempByte |= mask;
@@ -971,25 +973,45 @@ namespace OpenSim.Region.CoreModules.World.Land
private bool[,] ConvertBytesToLandBitmap()
{
- bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax];
+ bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
tempConvertMap.Initialize();
byte tempByte = 0;
- int x = 0, y = 0, i = 0, bitNum = 0;
- for (i = 0; i < 512; i++)
+ // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
+ int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
+ int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
+
+ if (bitmapLen == 512)
+ {
+ // Legacy bitmap being passed in. Use the legacy region size
+ // and only set the lower area of the larger region.
+ xLen = (int)(Constants.RegionSize / landUnit);
+ }
+ // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
+
+ int x = 0, y = 0;
+ for (int i = 0; i < bitmapLen; i++)
{
tempByte = LandData.Bitmap[i];
- for (bitNum = 0; bitNum < 8; bitNum++)
+ for (int bitNum = 0; bitNum < 8; bitNum++)
{
bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
- tempConvertMap[x, y] = bit;
+ try
+ {
+ tempConvertMap[x, y] = bit;
+ }
+ catch (Exception)
+ {
+ m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
+ }
x++;
- if (x > 63)
+ if (x >= xLen)
{
x = 0;
y++;
}
}
}
+
return tempConvertMap;
}
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index bc52a4361e..c7ffeafae9 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -102,7 +102,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
terrainRenderer.Initialise(m_scene, m_config);
- mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
+ mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height,
+ System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//long t = System.Environment.TickCount;
//for (int i = 0; i < 10; ++i) {
terrainRenderer.TerrainToBitmap(mapbmp);
@@ -277,7 +278,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
{
int tc = 0;
- double[,] hm = whichScene.Heightmap.GetDoubles();
+ ITerrainChannel hm = whichScene.Heightmap;
tc = Environment.TickCount;
m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
EntityBase[] objs = whichScene.GetEntities();
@@ -363,7 +364,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
Vector3 pos = part.GetWorldPosition();
// skip prim outside of retion
- if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
+ if (!m_scene.PositionIsInCurrentRegion(pos))
continue;
// skip prim in non-finite position
@@ -388,7 +389,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
Vector3 scale = new Vector3();
Vector3 tScale = new Vector3();
- Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
+ Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z);
Quaternion llrot = part.GetWorldRotation();
Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
@@ -406,9 +407,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
int mapdrawendY = (int)(pos.Y + scale.Y);
// If object is beyond the edge of the map, don't draw it to avoid errors
- if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
- || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
- || mapdrawendY > ((int)Constants.RegionSize - 1))
+ if (mapdrawstartX < 0
+ || mapdrawstartX > (hm.Width - 1)
+ || mapdrawendX < 0
+ || mapdrawendX > (hm.Width - 1)
+ || mapdrawstartY < 0
+ || mapdrawstartY > (hm.Height - 1)
+ || mapdrawendY < 0
+ || mapdrawendY > (hm.Height - 1))
continue;
#region obb face reconstruction part duex
@@ -530,11 +536,11 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
for (int i = 0; i < FaceA.Length; i++)
{
Point[] working = new Point[5];
- working[0] = project(FaceA[i], axPos);
- working[1] = project(FaceB[i], axPos);
- working[2] = project(FaceD[i], axPos);
- working[3] = project(FaceC[i], axPos);
- working[4] = project(FaceA[i], axPos);
+ working[0] = project(hm, FaceA[i], axPos);
+ working[1] = project(hm, FaceB[i], axPos);
+ working[2] = project(hm, FaceD[i], axPos);
+ working[3] = project(hm, FaceC[i], axPos);
+ working[4] = project(hm, FaceA[i], axPos);
face workingface = new face();
workingface.pts = working;
@@ -609,17 +615,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
return mapbmp;
}
- private Point project(Vector3 point3d, Vector3 originpos)
+ private Point project(ITerrainChannel hm, Vector3 point3d, Vector3 originpos)
{
Point returnpt = new Point();
//originpos = point3d;
//int d = (int)(256f / 1.5f);
//Vector3 topos = new Vector3(0, 0, 0);
- // float z = -point3d.z - topos.z;
+ // float z = -point3d.z - topos.z;
returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d);
- returnpt.Y = (int)(((int)Constants.RegionSize - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
+ returnpt.Y = (int)((hm.Width - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
return returnpt;
}
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index cb06fd4490..708286c906 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -31,6 +31,7 @@ using System.Reflection;
using log4net;
using Nini.Config;
using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.World.LegacyMap
@@ -39,8 +40,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
{
private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
- private static readonly ILog m_log =
- LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]";
private Scene m_scene;
//private IConfigSource m_config; // not used currently
@@ -53,19 +54,26 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
public void TerrainToBitmap(Bitmap mapbmp)
{
+ m_log.DebugFormat("{0} Generating Maptile Step 1: Terrain", LogHeader);
int tc = Environment.TickCount;
- m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
- double[,] hm = m_scene.Heightmap.GetDoubles();
+ ITerrainChannel hm = m_scene.Heightmap;
+
+ if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
+ {
+ m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
+ LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
+ }
+
bool ShadowDebugContinue = true;
bool terraincorruptedwarningsaid = false;
float low = 255;
float high = 0;
- for (int x = 0; x < (int)Constants.RegionSize; x++)
+ for (int x = 0; x < hm.Width; x++)
{
- for (int y = 0; y < (int)Constants.RegionSize; y++)
+ for (int y = 0; y < hm.Height; y++)
{
float hmval = (float)hm[x, y];
if (hmval < low)
@@ -77,12 +85,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
- for (int x = 0; x < (int)Constants.RegionSize; x++)
+ for (int x = 0; x < hm.Width; x++)
{
- for (int y = 0; y < (int)Constants.RegionSize; y++)
+ for (int y = 0; y < hm.Height; y++)
{
// Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
- int yr = ((int)Constants.RegionSize - 1) - y;
+ int yr = ((int)hm.Height - 1) - y;
float heightvalue = (float)hm[x, y];
@@ -109,12 +117,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
// .
//
// Shade the terrain for shadows
- if (x < ((int)Constants.RegionSize - 1) && yr < ((int)Constants.RegionSize - 1))
+ if (x < (hm.Width - 1) && yr < (hm.Height - 1))
{
float hfvalue = (float)hm[x, y];
float hfvaluecompare = 0f;
- if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize))
+ if ((x + 1 < hm.Width) && (y + 1 < hm.Height))
{
hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there
}
@@ -179,7 +187,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
if (ShadowDebugContinue)
{
- if ((x - 1 > 0) && (yr + 1 < (int)Constants.RegionSize))
+ if ((x - 1 > 0) && (yr + 1 < hm.Height))
{
color = mapbmp.GetPixel(x - 1, yr + 1);
int r = color.R;
@@ -233,7 +241,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
terraincorruptedwarningsaid = true;
}
Color black = Color.Black;
- mapbmp.SetPixel(x, ((int)Constants.RegionSize - y) - 1, black);
+ mapbmp.SetPixel(x, (hm.Width - y) - 1, black);
}
}
}
@@ -242,4 +250,4 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index d4e4c252cc..014c84575e 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -151,14 +151,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
break;
case 2: // Sell a copy
- Vector3 inventoryStoredPosition = new Vector3
- (((group.AbsolutePosition.X > (int)Constants.RegionSize)
- ? 250
- : group.AbsolutePosition.X)
- ,
- (group.AbsolutePosition.X > (int)Constants.RegionSize)
- ? 250
- : group.AbsolutePosition.X,
+ Vector3 inventoryStoredPosition = new Vector3(
+ Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6),
+ Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6),
group.AbsolutePosition.Z);
Vector3 originalPosition = group.AbsolutePosition;
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 616fe98082..928755dcc7 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -1571,10 +1571,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
float X = position.X;
float Y = position.Y;
- if (X > ((int)Constants.RegionSize - 1))
- X = ((int)Constants.RegionSize - 1);
- if (Y > ((int)Constants.RegionSize - 1))
- Y = ((int)Constants.RegionSize - 1);
+ if (X > ((int)m_scene.RegionInfo.RegionSizeX - 1))
+ X = ((int)m_scene.RegionInfo.RegionSizeX - 1);
+ if (Y > ((int)m_scene.RegionInfo.RegionSizeY - 1))
+ Y = ((int)m_scene.RegionInfo.RegionSizeY - 1);
if (X < 0)
X = 0;
if (Y < 0)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
index 7186dd7d55..80396c41cc 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
for (y = 0; y < map.Height; y++)
{
map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
- double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01;
+ double spherFac = TerrainUtil.SphericalFactor(x, y, map.Width / 2, map.Height / 2, 50) * 0.01;
if (map[x, y] < spherFac)
{
map[x, y] = spherFac;
@@ -53,4 +53,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d78ade5fa7..d5c77ec3e1 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
{
using (Bitmap bitmap = new Bitmap(filename))
{
- ITerrainChannel retval = new TerrainChannel(true);
+ ITerrainChannel retval = new TerrainChannel(w, h);
for (int x = 0; x < retval.Width; x++)
{
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
index b5c7d336cb..a7e4d9fd79 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
@@ -154,10 +154,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
public ITerrainChannel LoadStream(Stream s)
{
-
+ // Set to default size
int w = (int)Constants.RegionSize;
int h = (int)Constants.RegionSize;
+ // create a dummy channel (in case data is bad)
TerrainChannel retval = new TerrainChannel(w, h);
BinaryReader bs = new BinaryReader(s);
@@ -165,8 +166,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
bool eof = false;
if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ")
{
-// int fileWidth = w;
-// int fileHeight = h;
// Terragen file
while (eof == false)
@@ -175,31 +174,29 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
switch (tmp)
{
case "SIZE":
-// int sztmp = bs.ReadInt16() + 1;
-// fileWidth = sztmp;
-// fileHeight = sztmp;
- bs.ReadInt16();
+ w = bs.ReadInt16() + 1;
+ h = w;
bs.ReadInt16();
break;
case "XPTS":
-// fileWidth = bs.ReadInt16();
- bs.ReadInt16();
+ w = bs.ReadInt16();
bs.ReadInt16();
break;
case "YPTS":
-// fileHeight = bs.ReadInt16();
- bs.ReadInt16();
+ h = bs.ReadInt16();
bs.ReadInt16();
break;
case "ALTW":
eof = true;
- Int16 heightScale = bs.ReadInt16();
- Int16 baseHeight = bs.ReadInt16();
+ // create new channel of proper size (now that we know it)
+ retval = new TerrainChannel(w, h);
+ double heightScale = (double)bs.ReadInt16() / 65536.0;
+ double baseHeight = (double)bs.ReadInt16();
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
- retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0;
+ retval[x, y] = baseHeight + (double)bs.ReadInt16() * heightScale;
}
}
break;
@@ -257,17 +254,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
bs.Write(enc.GetBytes("TERRAGENTERRAIN "));
bs.Write(enc.GetBytes("SIZE"));
- bs.Write(Convert.ToInt16(Constants.RegionSize));
+ bs.Write(Convert.ToInt16(map.Width));
bs.Write(Convert.ToInt16(0)); // necessary padding
//The XPTS and YPTS chunks are not needed for square regions
//but L3DT won't load the terrain file properly without them.
bs.Write(enc.GetBytes("XPTS"));
- bs.Write(Convert.ToInt16(Constants.RegionSize));
+ bs.Write(Convert.ToInt16(map.Width));
bs.Write(Convert.ToInt16(0)); // necessary padding
bs.Write(enc.GetBytes("YPTS"));
- bs.Write(Convert.ToInt16(Constants.RegionSize));
+ bs.Write(Convert.ToInt16(map.Height));
bs.Write(Convert.ToInt16(0)); // necessary padding
bs.Write(enc.GetBytes("SCAL"));
@@ -283,11 +280,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
bs.Write(Convert.ToInt16(horizontalScale)); // range between max and min
bs.Write(Convert.ToInt16(baseHeight)); // base height or mid point
+ double factor = 65536.0 / horizontalScale; // avoid computing this on each iteration
+
for (int y = 0; y < map.Height; y++)
{
for (int x = 0; x < map.Width; x++)
{
- float elevation = (float)((map[x,y] - baseHeight) * 65536 ) / (float)horizontalScale; // see LoadStream for inverse
+ float elevation = (float)((map[x,y] - baseHeight) * factor); // see LoadStream for inverse
// clamp rounding issues
if (elevation > Int16.MaxValue)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
index 630473e162..d3e2533628 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
{
if (fillArea[x, y])
{
- double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0);
+ double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
map[x, y] += noise * strength;
}
@@ -55,4 +55,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
index 989b7d8019..e7df3f8d4c 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
z *= z;
z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
- double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0);
+ double noise = TerrainUtil.PerlinNoise2D(x / (double) map.Width, y / (double) map.Height, 8, 1.0);
if (z > 0.0)
map[x, y] += noise * z * duration;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 4d738a58ec..9a88804a72 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -71,6 +71,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+#pragma warning disable 414
+ private static readonly string LogHeader = "[TERRAIN MODULE]";
+#pragma warning restore 414
+
private readonly Commander m_commander = new Commander("terrain");
private readonly Dictionary m_floodeffects =
@@ -81,8 +85,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private readonly Dictionary m_painteffects =
new Dictionary();
- private ITerrainChannel m_channel;
private Dictionary m_plugineffects;
+ private ITerrainChannel m_channel;
private ITerrainChannel m_revert;
private Scene m_scene;
private volatile bool m_tainted;
@@ -90,6 +94,85 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private String m_InitialTerrain = "pinhead-island";
+ // If true, send terrain patch updates to clients based on their view distance
+ private bool m_sendTerrainUpdatesByViewDistance = true;
+
+ // Class to keep the per client collection of terrain patches that must be sent.
+ // A patch is set to 'true' meaning it should be sent to the client. Once the
+ // patch packet is queued to the client, the bit for that patch is set to 'false'.
+ private class PatchUpdates
+ {
+ private bool[,] updated; // for each patch, whether it needs to be sent to this client
+ private int updateCount; // number of patches that need to be sent
+ public ScenePresence Presence; // a reference to the client to send to
+ public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
+ {
+ updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
+ updateCount = 0;
+ Presence = pPresence;
+ // Initially, send all patches to the client
+ SetAll(true);
+ }
+ // Returns 'true' if there are any patches marked for sending
+ public bool HasUpdates()
+ {
+ return (updateCount > 0);
+ }
+ public void SetByXY(int x, int y, bool state)
+ {
+ this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
+ }
+ public bool GetByPatch(int patchX, int patchY)
+ {
+ return updated[patchX, patchY];
+ }
+ public void SetByPatch(int patchX, int patchY, bool state)
+ {
+ bool prevState = updated[patchX, patchY];
+ if (!prevState && state)
+ updateCount++;
+ if (prevState && !state)
+ updateCount--;
+ updated[patchX, patchY] = state;
+ }
+ public void SetAll(bool state)
+ {
+ updateCount = 0;
+ for (int xx = 0; xx < updated.GetLength(0); xx++)
+ for (int yy = 0; yy < updated.GetLength(1); yy++)
+ updated[xx, yy] = state;
+ if (state)
+ updateCount = updated.GetLength(0) * updated.GetLength(1);
+ }
+ // Logically OR's the terrain data's patch taint map into this client's update map.
+ public void SetAll(TerrainData terrData)
+ {
+ if (updated.GetLength(0) != (terrData.SizeX / Constants.TerrainPatchSize)
+ || updated.GetLength(1) != (terrData.SizeY / Constants.TerrainPatchSize))
+ {
+ throw new Exception(
+ String.Format("{0} PatchUpdates.SetAll: patch array not same size as terrain. arr=<{1},{2}>, terr=<{3},{4}>",
+ LogHeader, updated.GetLength(0), updated.GetLength(1),
+ terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
+ );
+ }
+ for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
+ {
+ for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
+ {
+ // Only set tainted. The patch bit may be set if the patch was to be sent later.
+ if (terrData.IsTaintedAt(xx, yy, false))
+ {
+ this.SetByXY(xx, yy, true);
+ }
+ }
+ }
+ }
+ }
+
+ // The flags of which terrain patches to send for each of the ScenePresence's
+ private Dictionary m_perClientPatchUpdates = new Dictionary();
+
///
/// Human readable list of terrain file extensions that are supported.
///
@@ -118,7 +201,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
IConfig terrainConfig = config.Configs["Terrain"];
if (terrainConfig != null)
+ {
m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
+ m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance);
+ }
}
public void AddRegion(Scene scene)
@@ -130,22 +216,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
if (m_scene.Heightmap == null)
{
- m_channel = new TerrainChannel(m_InitialTerrain);
+ m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX,
+ (int)m_scene.RegionInfo.RegionSizeY,
+ (int)m_scene.RegionInfo.RegionSizeZ);
m_scene.Heightmap = m_channel;
- m_revert = new TerrainChannel();
UpdateRevertMap();
}
else
{
m_channel = m_scene.Heightmap;
- m_revert = new TerrainChannel();
UpdateRevertMap();
}
m_scene.RegisterModuleInterface(this);
m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
+ m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
+ m_scene.EventManager.OnFrame += EventManager_OnFrame;
}
InstallDefaultEffects();
@@ -184,8 +272,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
// remove the commands
m_scene.UnregisterModuleCommander(m_commander.Name);
// remove the event-handlers
+ m_scene.EventManager.OnFrame -= EventManager_OnFrame;
m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick;
m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
+ m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
m_scene.EventManager.OnNewClient -= EventManager_OnNewClient;
// remove the interface
m_scene.UnregisterModuleInterface(this);
@@ -230,11 +320,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
try
{
ITerrainChannel channel = loader.Value.LoadFile(filename);
- if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize)
+ if (channel.Width != m_scene.RegionInfo.RegionSizeX || channel.Height != m_scene.RegionInfo.RegionSizeY)
{
// TerrainChannel expects a RegionSize x RegionSize map, currently
throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}",
- Constants.RegionSize, Constants.RegionSize));
+ m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY));
}
m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
m_scene.Heightmap = channel;
@@ -261,7 +351,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
String.Format("Unable to load heightmap: {0}", e.Message));
}
}
- CheckForTerrainUpdates();
m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
return;
}
@@ -309,12 +398,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
LoadFromStream(filename, URIFetch(pathToTerrainHeightmap));
}
+ public void LoadFromStream(string filename, Stream stream)
+ {
+ LoadFromStream(filename, Vector3.Zero, 0f, Vector2.Zero, stream);
+ }
+
///
/// Loads a terrain file from a stream and installs it in the scene.
///
/// Filename to terrain file. Type is determined by extension.
///
- public void LoadFromStream(string filename, Stream stream)
+ public void LoadFromStream(string filename, Vector3 displacement,
+ float radianRotation, Vector2 rotationDisplacement, Stream stream)
{
foreach (KeyValuePair loader in m_loaders)
{
@@ -325,8 +420,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
try
{
ITerrainChannel channel = loader.Value.LoadStream(stream);
- m_scene.Heightmap = channel;
- m_channel = channel;
+ m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
UpdateRevertMap();
}
catch (NotImplementedException)
@@ -337,7 +431,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
}
- CheckForTerrainUpdates();
m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
return;
}
@@ -406,9 +499,46 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
}
+ // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
+ // ITerrainModule.TaintTerrain()
public void TaintTerrain ()
{
- CheckForTerrainUpdates();
+ lock (m_perClientPatchUpdates)
+ {
+ // Set the flags for all clients so the tainted patches will be sent out
+ foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
+ {
+ pups.SetAll(m_scene.Heightmap.GetTerrainData());
+ }
+ }
+ }
+
+ // ITerrainModule.PushTerrain()
+ public void PushTerrain(IClientAPI pClient)
+ {
+ if (m_sendTerrainUpdatesByViewDistance)
+ {
+ ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
+ if (presence != null)
+ {
+ lock (m_perClientPatchUpdates)
+ {
+ PatchUpdates pups;
+ if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
+ {
+ // There is a ScenePresence without a send patch map. Create one.
+ pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
+ m_perClientPatchUpdates.Add(presence.UUID, pups);
+ }
+ pups.SetAll(true);
+ }
+ }
+ }
+ else
+ {
+ // The traditional way is to call into the protocol stack to send them all.
+ pClient.SendLayerData(new float[10]);
+ }
}
#region Plugin Loading Methods
@@ -532,6 +662,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
///
public void UpdateRevertMap()
{
+ /*
int x;
for (x = 0; x < m_channel.Width; x++)
{
@@ -541,6 +672,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_revert[x, y] = m_channel[x, y];
}
}
+ */
+ m_revert = m_channel.MakeCopy();
}
///
@@ -567,8 +700,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
fileWidth, fileHeight,
- (int) Constants.RegionSize,
- (int) Constants.RegionSize);
+ (int) m_scene.RegionInfo.RegionSizeX,
+ (int) m_scene.RegionInfo.RegionSizeY);
m_scene.Heightmap = channel;
m_channel = channel;
UpdateRevertMap();
@@ -615,8 +748,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
fileWidth, fileHeight,
- (int)Constants.RegionSize,
- (int)Constants.RegionSize);
+ (int)m_scene.RegionInfo.RegionSizeX,
+ (int)m_scene.RegionInfo.RegionSizeY);
MainConsole.Instance.OutputFormat(
"Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}",
@@ -633,8 +766,45 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave);
}
+ ///
+ /// Called before processing of every simulation frame.
+ /// This is used to check to see of any of the terrain is tainted and, if so, schedule
+ /// updates for all the presences.
+ /// This also checks to see if there are updates that need to be sent for each presence.
+ /// This is where the logic is to send terrain updates to clients.
+ ///
+ private void EventManager_OnFrame()
+ {
+ TerrainData terrData = m_channel.GetTerrainData();
+
+ bool shouldTaint = false;
+ for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
+ {
+ for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
+ {
+ if (terrData.IsTaintedAt(x, y))
+ {
+ // Found a patch that was modified. Push this flag into the clients.
+ SendToClients(terrData, x, y);
+ shouldTaint = true;
+ }
+ }
+ }
+
+ // This event also causes changes to be sent to the clients
+ CheckSendingPatchesToClients();
+
+ // If things changes, generate some events
+ if (shouldTaint)
+ {
+ m_scene.EventManager.TriggerTerrainTainted();
+ m_tainted = true;
+ }
+ }
+
///
/// Performs updates to the region periodically, synchronising physics and other heightmap aware sections
+ /// Called infrequently (like every 5 seconds or so). Best used for storing terrain.
///
private void EventManager_OnTerrainTick()
{
@@ -644,8 +814,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
m_scene.SaveTerrain();
- m_scene.EventManager.TriggerTerrainUpdate();
-
// Clients who look at the map will never see changes after they looked at the map, so i've commented this out.
//m_scene.CreateTerrainTexture(true);
}
@@ -687,54 +855,48 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
///
- /// Checks to see if the terrain has been modified since last check
- /// but won't attempt to limit those changes to the limits specified in the estate settings
- /// currently invoked by the command line operations in the region server only
+ /// Installs terrain brush hook to IClientAPI
///
- private void CheckForTerrainUpdates()
+ ///
+ private void EventManager_OnClientClosed(UUID client, Scene scene)
{
- CheckForTerrainUpdates(false);
- }
-
- ///
- /// Checks to see if the terrain has been modified since last check.
- /// If it has been modified, every all the terrain patches are sent to the client.
- /// If the call is asked to respect the estate settings for terrain_raise_limit and
- /// terrain_lower_limit, it will clamp terrain updates between these values
- /// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
- /// should height map deltas be limited to the estate settings limits
- ///
- private void CheckForTerrainUpdates(bool respectEstateSettings)
- {
- bool shouldTaint = false;
- float[] serialised = m_channel.GetFloatsSerialised();
- int x;
- for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
+ ScenePresence presence = scene.GetScenePresence(client);
+ if (presence != null)
{
- int y;
- for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize)
- {
- if (m_channel.Tainted(x, y))
- {
- // if we should respect the estate settings then
- // fixup and height deltas that don't respect them
- if (respectEstateSettings && LimitChannelChanges(x, y))
- {
- // this has been vetoed, so update
- // what we are going to send to the client
- serialised = m_channel.GetFloatsSerialised();
- }
+ presence.ControllingClient.OnModifyTerrain -= client_OnModifyTerrain;
+ presence.ControllingClient.OnBakeTerrain -= client_OnBakeTerrain;
+ presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
+ presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
+ }
- SendToClients(serialised, x, y);
- shouldTaint = true;
+ lock (m_perClientPatchUpdates)
+ m_perClientPatchUpdates.Remove(client);
+ }
+
+ ///
+ /// Scan over changes in the terrain and limit height changes. This enforces the
+ /// non-estate owner limits on rate of terrain editting.
+ /// Returns 'true' if any heights were limited.
+ ///
+ private bool EnforceEstateLimits()
+ {
+ TerrainData terrData = m_channel.GetTerrainData();
+
+ bool wasLimited = false;
+ for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
+ {
+ for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
+ {
+ if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
+ {
+ // If we should respect the estate settings then
+ // fixup and height deltas that don't respect them.
+ // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
+ wasLimited |= LimitChannelChanges(terrData, x, y);
}
}
}
- if (shouldTaint)
- {
- m_scene.EventManager.TriggerTerrainTainted();
- m_tainted = true;
- }
+ return wasLimited;
}
///
@@ -742,11 +904,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// are all within the current estate limits
/// true if changes were limited, false otherwise
///
- private bool LimitChannelChanges(int xStart, int yStart)
+ private bool LimitChannelChanges(TerrainData terrData, int xStart, int yStart)
{
bool changesLimited = false;
- double minDelta = m_scene.RegionInfo.RegionSettings.TerrainLowerLimit;
- double maxDelta = m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
+ float minDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit;
+ float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
// loop through the height map for this patch and compare it against
// the revert map
@@ -754,19 +916,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
{
-
- double requestedHeight = m_channel[x, y];
- double bakedHeight = m_revert[x, y];
- double requestedDelta = requestedHeight - bakedHeight;
+ float requestedHeight = terrData[x, y];
+ float bakedHeight = (float)m_revert[x, y];
+ float requestedDelta = requestedHeight - bakedHeight;
if (requestedDelta > maxDelta)
{
- m_channel[x, y] = bakedHeight + maxDelta;
+ terrData[x, y] = bakedHeight + maxDelta;
changesLimited = true;
}
else if (requestedDelta < minDelta)
{
- m_channel[x, y] = bakedHeight + minDelta; //as lower is a -ve delta
+ terrData[x, y] = bakedHeight + minDelta; //as lower is a -ve delta
changesLimited = true;
}
}
@@ -794,14 +955,154 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// A copy of the terrain as a 1D float array of size w*h
/// The patch corner to send
/// The patch corner to send
- private void SendToClients(float[] serialised, int x, int y)
+ private void SendToClients(TerrainData terrData, int x, int y)
{
- m_scene.ForEachClient(
- delegate(IClientAPI controller)
- { controller.SendLayerData(
- x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
+ if (m_sendTerrainUpdatesByViewDistance)
+ {
+ // Add that this patch needs to be sent to the accounting for each client.
+ lock (m_perClientPatchUpdates)
+ {
+ m_scene.ForEachScenePresence(presence =>
+ {
+ PatchUpdates thisClientUpdates;
+ if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
+ {
+ // There is a ScenePresence without a send patch map. Create one.
+ thisClientUpdates = new PatchUpdates(terrData, presence);
+ m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
+ }
+ thisClientUpdates.SetByXY(x, y, true);
+ }
+ );
+ }
+ }
+ else
+ {
+ // Legacy update sending where the update is sent out as soon as noticed
+ // We know the actual terrain data passed is ignored. This kludge saves changing IClientAPI.
+ //float[] heightMap = terrData.GetFloatsSerialized();
+ float[] heightMap = new float[10];
+ m_scene.ForEachClient(
+ delegate(IClientAPI controller)
+ {
+ controller.SendLayerData(x / Constants.TerrainPatchSize,
+ y / Constants.TerrainPatchSize,
+ heightMap);
}
- );
+ );
+ }
+ }
+
+ private class PatchesToSend : IComparable
+ {
+ public int PatchX;
+ public int PatchY;
+ public float Dist;
+ public PatchesToSend(int pX, int pY, float pDist)
+ {
+ PatchX = pX;
+ PatchY = pY;
+ Dist = pDist;
+ }
+ public int CompareTo(PatchesToSend other)
+ {
+ return Dist.CompareTo(other.Dist);
+ }
+ }
+
+ // Called each frame time to see if there are any patches to send to any of the
+ // ScenePresences.
+ // Loop through all the per-client info and send any patches necessary.
+ private void CheckSendingPatchesToClients()
+ {
+ lock (m_perClientPatchUpdates)
+ {
+ foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
+ {
+ if (pups.HasUpdates())
+ {
+ // There is something that could be sent to this client.
+ List toSend = GetModifiedPatchesInViewDistance(pups);
+ if (toSend.Count > 0)
+ {
+ // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
+ // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
+ // Sort the patches to send by the distance from the presence
+ toSend.Sort();
+ /*
+ foreach (PatchesToSend pts in toSend)
+ {
+ pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
+ // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
+ }
+ */
+
+ int[] xPieces = new int[toSend.Count];
+ int[] yPieces = new int[toSend.Count];
+ float[] patchPieces = new float[toSend.Count * 2];
+ int pieceIndex = 0;
+ foreach (PatchesToSend pts in toSend)
+ {
+ patchPieces[pieceIndex++] = pts.PatchX;
+ patchPieces[pieceIndex++] = pts.PatchY;
+ }
+ pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
+ }
+ }
+ }
+ }
+ }
+
+ private List GetModifiedPatchesInViewDistance(PatchUpdates pups)
+ {
+ List ret = new List();
+
+ ScenePresence presence = pups.Presence;
+ if (presence == null)
+ return ret;
+
+ // Compute the area of patches within our draw distance
+ int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
+ startX = Math.Max(startX, 0);
+ startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
+ int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
+ startY = Math.Max(startY, 0);
+ startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
+ int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
+ endX = Math.Max(endX, 0);
+ endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
+ int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
+ endY = Math.Max(endY, 0);
+ endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
+ // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
+ // LogHeader, m_scene.RegionInfo.RegionName,
+ // presence.DrawDistance, presence.AbsolutePosition,
+ // startX, startY, endX, endY);
+ for (int x = startX; x < endX; x++)
+ {
+ for (int y = startY; y < endY; y++)
+ {
+ //Need to make sure we don't send the same ones over and over
+ Vector3 presencePos = presence.AbsolutePosition;
+ Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
+ if (pups.GetByPatch(x, y))
+ {
+ //Check which has less distance, camera or avatar position, both have to be done.
+ //Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off
+ if (Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50)
+ || Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
+ {
+ //They can see it, send it to them
+ pups.SetByPatch(x, y, false);
+ float dist = Vector3.DistanceSquared(presencePos, patchPos);
+ ret.Add(new PatchesToSend(x, y, dist));
+ //Wait and send them all at once
+ // pups.client.SendLayerData(x, y, null);
+ }
+ }
+ }
+ }
+ return ret;
}
private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
@@ -846,7 +1147,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_painteffects[(StandardTerrainEffects) action].PaintEffect(
m_channel, allowMask, west, south, height, size, seconds);
- CheckForTerrainUpdates(!god); //revert changes outside estate limits
+ //revert changes outside estate limits
+ if (!god)
+ EnforceEstateLimits();
}
}
else
@@ -884,10 +1187,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (allowed)
{
StoreUndoState();
- m_floodeffects[(StandardTerrainEffects) action].FloodEffect(
- m_channel, fillArea, size);
+ m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size);
- CheckForTerrainUpdates(!god); //revert changes outside estate limits
+ //revert changes outside estate limits
+ if (!god)
+ EnforceEstateLimits();
}
}
else
@@ -911,7 +1215,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
protected void client_OnUnackedTerrain(IClientAPI client, int patchX, int patchY)
{
//m_log.Debug("Terrain packet unacked, resending patch: " + patchX + " , " + patchY);
- client.SendLayerData(patchX, patchY, m_scene.Heightmap.GetFloatsSerialised());
+ // SendLayerData does not use the heightmap parameter. This kludge is so as to not change IClientAPI.
+ float[] heightMap = new float[10];
+ client.SendLayerData(patchX, patchY, heightMap);
}
private void StoreUndoState()
@@ -938,7 +1244,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void InterfaceLoadFile(Object[] args)
{
LoadFromFile((string) args[0]);
- CheckForTerrainUpdates();
}
private void InterfaceLoadTileFile(Object[] args)
@@ -948,7 +1253,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
(int) args[2],
(int) args[3],
(int) args[4]);
- CheckForTerrainUpdates();
}
private void InterfaceSaveFile(Object[] args)
@@ -977,7 +1281,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] = m_revert[x, y];
- CheckForTerrainUpdates();
}
private void InterfaceFlipTerrain(Object[] args)
@@ -986,28 +1289,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (direction.ToLower().StartsWith("y"))
{
- for (int x = 0; x < Constants.RegionSize; x++)
+ for (int x = 0; x < m_channel.Width; x++)
{
- for (int y = 0; y < Constants.RegionSize / 2; y++)
+ for (int y = 0; y < m_channel.Height / 2; y++)
{
double height = m_channel[x, y];
- double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y];
+ double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
m_channel[x, y] = flippedHeight;
- m_channel[x, (int)Constants.RegionSize - 1 - y] = height;
+ m_channel[x, (int)m_channel.Height - 1 - y] = height;
}
}
}
else if (direction.ToLower().StartsWith("x"))
{
- for (int y = 0; y < Constants.RegionSize; y++)
+ for (int y = 0; y < m_channel.Height; y++)
{
- for (int x = 0; x < Constants.RegionSize / 2; x++)
+ for (int x = 0; x < m_channel.Width / 2; x++)
{
double height = m_channel[x, y];
- double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y];
+ double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
m_channel[x, y] = flippedHeight;
- m_channel[(int)Constants.RegionSize - 1 - x, y] = height;
+ m_channel[(int)m_channel.Width - 1 - x, y] = height;
}
}
@@ -1016,9 +1319,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{
m_log.Error("Unrecognised direction - need x or y");
}
-
-
- CheckForTerrainUpdates();
}
private void InterfaceRescaleTerrain(Object[] args)
@@ -1076,7 +1376,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
}
- CheckForTerrainUpdates();
}
}
@@ -1087,7 +1386,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] += (double) args[0];
- CheckForTerrainUpdates();
}
private void InterfaceMultiplyTerrain(Object[] args)
@@ -1096,7 +1394,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] *= (double) args[0];
- CheckForTerrainUpdates();
}
private void InterfaceLowerTerrain(Object[] args)
@@ -1105,17 +1402,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] -= (double) args[0];
- CheckForTerrainUpdates();
}
- private void InterfaceFillTerrain(Object[] args)
+ public void InterfaceFillTerrain(Object[] args)
{
int x, y;
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] = (double) args[0];
- CheckForTerrainUpdates();
}
private void InterfaceMinTerrain(Object[] args)
@@ -1128,7 +1423,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
}
}
- CheckForTerrainUpdates();
}
private void InterfaceMaxTerrain(Object[] args)
@@ -1141,7 +1435,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
}
}
- CheckForTerrainUpdates();
}
private void InterfaceShowDebugStats(Object[] args)
@@ -1204,7 +1497,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (m_plugineffects.ContainsKey(firstArg))
{
m_plugineffects[firstArg].RunEffect(m_channel);
- CheckForTerrainUpdates();
}
else
{
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index be719ea2d3..062d7fff2d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -40,10 +40,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
[Test]
public void BrushTest()
{
+ int midRegion = (int)Constants.RegionSize / 2;
+
+ // Create a mask that covers only the left half of the region
bool[,] allowMask = new bool[(int)Constants.RegionSize, 256];
int x;
int y;
- for (x = 0; x < (int)((int)Constants.RegionSize * 0.5f); x++)
+ for (x = 0; x < midRegion; x++)
{
for (y = 0; y < (int)Constants.RegionSize; y++)
{
@@ -57,13 +60,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
ITerrainPaintableEffect effect = new RaiseSphere();
- effect.PaintEffect(map, allowMask, (int)Constants.RegionSize * 0.5f, (int)Constants.RegionSize * 0.5f, -1.0, 2, 0.1);
- Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (127,128).");
- Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] > 0.0, "Raise brush should raising value at this point (124,128).");
- Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (123,128).");
- Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (128,128).");
- Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Raise brush should not change value at this point (0,128).");
-
+ effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
+ Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
+ Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
+ Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
+ Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128).");
+ Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128).");
//
// Test LowerSphere
//
@@ -77,13 +79,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
}
effect = new LowerSphere();
- effect.PaintEffect(map, allowMask, ((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), -1.0, 2, 6.0);
- Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
- Assert.That(map[127, (int)((int)Constants.RegionSize * 0.5f)] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
- Assert.That(map[124, (int)((int)Constants.RegionSize * 0.5f)] < 1.0, "Lower brush should lowering value at this point (124,128).");
- Assert.That(map[123, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (123,128).");
- Assert.That(map[128, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (128,128).");
- Assert.That(map[0, (int)((int)Constants.RegionSize * 0.5f)] == 1.0, "Lower brush should not change value at this point (0,128).");
+ effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0);
+ Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
+ Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
+ Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
+ Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128).");
+ Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128).");
+ Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128).");
}
[Test]
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
index e03ac5a26f..c6f531edd2 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
@@ -55,5 +55,10 @@ namespace OpenSim.Region.Framework.Interfaces
/// Currently, will throw an exception if this does not match a root region.
///
Vector2 GetSizeOfMegaregion(UUID regionId);
+
+ ///
+ /// Tests to see of position (relative to the region) is within the megaregion
+ ///
+ bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy);
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 3e97a7ae3d..13358cb360 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -68,13 +68,22 @@ namespace OpenSim.Region.Framework.Interfaces
///
/// HeightField data
/// region UUID
+ void StoreTerrain(TerrainData terrain, UUID regionID);
+
+ // Legacy version kept for downward compabibility
void StoreTerrain(double[,] terrain, UUID regionID);
///
/// Load the latest terrain revision from region storage
///
/// the region UUID
+ /// the X dimension of the region being filled
+ /// the Y dimension of the region being filled
+ /// the Z dimension of the region being filled
/// Heightfield data
+ TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
+
+ // Legacy version kept for downward compabibility
double[,] LoadTerrain(UUID regionID);
void StoreLandObject(ILandObject Parcel);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 17bd48be67..e09f775642 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -79,13 +79,22 @@ namespace OpenSim.Region.Framework.Interfaces
///
/// HeightField data
/// region UUID
+ void StoreTerrain(TerrainData terrain, UUID regionID);
+
+ // Legacy version kept for downward compabibility
void StoreTerrain(double[,] terrain, UUID regionID);
///
/// Load the latest terrain revision from region storage
///
/// the region UUID
+ /// the X dimension of the terrain being filled
+ /// the Y dimension of the terrain being filled
+ /// the Z dimension of the terrain being filled
/// Heightfield data
+ TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
+
+ // Legacy version kept for downward compabibility
double[,] LoadTerrain(UUID regionID);
void StoreLandObject(ILandObject Parcel);
@@ -136,4 +145,5 @@ namespace OpenSim.Region.Framework.Interfaces
void Shutdown();
}
+
}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
index e467701351..f660b8dbe0 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -25,13 +25,23 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using OpenSim.Framework;
+using OpenMetaverse;
+
namespace OpenSim.Region.Framework.Interfaces
{
public interface ITerrainChannel
{
- int Height { get; }
+ int Width { get;} // X dimension
+ int Height { get;} // Y dimension
+ int Altitude { get;} // Z dimension
+
double this[int x, int y] { get; set; }
- int Width { get; }
+
+ float GetHeightAtXYZ(float x, float y, float z);
+
+ // Return the packaged terrain data for passing into lower levels of communication
+ TerrainData GetTerrainData();
///
/// Squash the entire heightmap into a single dimensioned array
@@ -40,9 +50,14 @@ namespace OpenSim.Region.Framework.Interfaces
float[] GetFloatsSerialised();
double[,] GetDoubles();
+
+ // Check if a location has been updated. Clears the taint flag as a side effect.
bool Tainted(int x, int y);
+
ITerrainChannel MakeCopy();
string SaveToXmlString();
void LoadFromXmlString(string data);
+ // Merge some terrain into this channel
+ void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement);
}
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index b45cc4d900..4ab5a4adee 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -2221,14 +2221,9 @@ namespace OpenSim.Region.Framework.Scenes
itemID = UUID.Zero;
if (grp != null)
{
- Vector3 inventoryStoredPosition = new Vector3
- (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
- ? 250
- : grp.AbsolutePosition.X)
- ,
- (grp.AbsolutePosition.X > (int)Constants.RegionSize)
- ? 250
- : grp.AbsolutePosition.X,
+ Vector3 inventoryStoredPosition = new Vector3(
+ Math.Min(grp.AbsolutePosition.X, RegionInfo.RegionSizeX - 6),
+ Math.Min(grp.AbsolutePosition.Y, RegionInfo.RegionSizeY - 6),
grp.AbsolutePosition.Z);
Vector3 originalPosition = grp.AbsolutePosition;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index eb34f557aa..46c904858c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -6,7 +6,7 @@
* 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 copyrightD
+ * * 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
@@ -103,7 +103,29 @@ namespace OpenSim.Region.Framework.Scenes
///
/// If false then physical objects are disabled, though collisions will continue as normal.
///
- public bool PhysicsEnabled { get; set; }
+ public bool PhysicsEnabled
+ {
+ get
+ {
+ return m_physicsEnabled;
+ }
+
+ set
+ {
+ m_physicsEnabled = value;
+
+ if (PhysicsScene != null)
+ {
+ IPhysicsParameters physScene = PhysicsScene as IPhysicsParameters;
+
+ if (physScene != null)
+ physScene.SetPhysicsParameter(
+ "Active", m_physicsEnabled.ToString(), PhysParameterEntry.APPLY_TO_NONE);
+ }
+ }
+ }
+
+ private bool m_physicsEnabled;
///
/// If false then scripts are not enabled on the smiulator
@@ -160,11 +182,6 @@ namespace OpenSim.Region.Framework.Scenes
///
public SimStatsReporter StatsReporter { get; private set; }
- public List NorthBorders = new List();
- public List EastBorders = new List();
- public List SouthBorders = new List();
- public List WestBorders = new List();
-
///
/// Controls whether physics can be applied to prims. Even if false, prims still have entries in a
/// PhysicsScene in order to perform collision detection
@@ -204,15 +221,16 @@ namespace OpenSim.Region.Framework.Scenes
///
public int m_linksetCapacity = 0;
+ public bool m_clampPrimSize;
+ public bool m_trustBinaries;
+ public bool m_allowScriptCrossings = true;
+
///
/// Max prims an Physical object will hold
///
///
public int m_linksetPhysCapacity = 0;
- public bool m_clampPrimSize;
- public bool m_trustBinaries;
- public bool m_allowScriptCrossings;
public bool m_useFlySlow;
public bool m_useTrashOnDelete = true;
@@ -364,7 +382,6 @@ namespace OpenSim.Region.Framework.Scenes
// TODO: Possibly stop other classes being able to manipulate this directly.
private SceneGraph m_sceneGraph;
- private volatile int m_bordersLocked;
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
private volatile bool m_backingup;
private Dictionary m_returns = new Dictionary();
@@ -446,18 +463,6 @@ namespace OpenSim.Region.Framework.Scenes
set { m_splitRegionID = value; }
}
- public bool BordersLocked
- {
- get { return m_bordersLocked == 1; }
- set
- {
- if (value == true)
- m_bordersLocked = 1;
- else
- m_bordersLocked = 0;
- }
- }
-
public new float TimeDilation
{
get { return m_sceneGraph.PhysicsScene.TimeDilation; }
@@ -1075,28 +1080,6 @@ namespace OpenSim.Region.Framework.Scenes
PeriodicBackup = true;
UseBackup = true;
- BordersLocked = true;
- Border northBorder = new Border();
- northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeY); //<---
- northBorder.CrossDirection = Cardinals.N;
- NorthBorders.Add(northBorder);
-
- Border southBorder = new Border();
- southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
- southBorder.CrossDirection = Cardinals.S;
- SouthBorders.Add(southBorder);
-
- Border eastBorder = new Border();
- eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, RegionInfo.RegionSizeX); //<---
- eastBorder.CrossDirection = Cardinals.E;
- EastBorders.Add(eastBorder);
-
- Border westBorder = new Border();
- westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,0); //--->
- westBorder.CrossDirection = Cardinals.W;
- WestBorders.Add(westBorder);
- BordersLocked = false;
-
m_eventManager = new EventManager();
m_permissions = new ScenePermissions(this);
@@ -1975,7 +1958,7 @@ namespace OpenSim.Region.Framework.Scenes
{
try
{
- double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID);
+ TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
if (map == null)
{
// This should be in the Terrain module, but it isn't because
@@ -1986,7 +1969,7 @@ namespace OpenSim.Region.Framework.Scenes
m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
- Heightmap = new TerrainChannel(m_InitialTerrain);
+ Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
}
@@ -2611,185 +2594,35 @@ namespace OpenSim.Region.Framework.Scenes
EntityTransferModule.Cross(grp, attemptedPosition, silent);
}
- public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
+ // Simple test to see if a position is in the current region.
+ // This test is mostly used to see if a region crossing is necessary.
+ // Assuming the position is relative to the region so anything outside its bounds.
+ // Return 'true' if position inside region.
+ public bool PositionIsInCurrentRegion(Vector3 pos)
{
- if (BordersLocked)
+ bool ret = false;
+ int xx = (int)Math.Floor(pos.X);
+ int yy = (int)Math.Floor(pos.Y);
+ if (xx < 0 || yy < 0)
+ return false;
+
+ IRegionCombinerModule regionCombinerModule = RequestModuleInterface();
+ if (regionCombinerModule == null)
{
- switch (gridline)
- {
- case Cardinals.N:
- lock (NorthBorders)
- {
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
- break;
- case Cardinals.S:
- lock (SouthBorders)
- {
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
-
- break;
- case Cardinals.E:
- lock (EastBorders)
- {
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
-
- break;
- case Cardinals.W:
-
- lock (WestBorders)
- {
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- }
- break;
-
- }
+ // Regular region. Just check for region size
+ if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY )
+ ret = true;
}
else
{
- switch (gridline)
- {
- case Cardinals.N:
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
-
- break;
- case Cardinals.S:
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- break;
- case Cardinals.E:
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return b;
- }
-
- break;
- case Cardinals.W:
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return b;
- }
- break;
-
- }
+ // We're in a mega-region so see if we are still in that larger region
+ ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
}
- return null;
+ return ret;
+
}
- public bool TestBorderCross(Vector3 position, Cardinals border)
- {
- if (BordersLocked)
- {
- switch (border)
- {
- case Cardinals.N:
- lock (NorthBorders)
- {
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- case Cardinals.E:
- lock (EastBorders)
- {
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- case Cardinals.S:
- lock (SouthBorders)
- {
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- case Cardinals.W:
- lock (WestBorders)
- {
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- }
- break;
- }
- }
- else
- {
- switch (border)
- {
- case Cardinals.N:
- foreach (Border b in NorthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- case Cardinals.E:
- foreach (Border b in EastBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- case Cardinals.S:
- foreach (Border b in SouthBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- case Cardinals.W:
- foreach (Border b in WestBorders)
- {
- if (b.TestCross(position))
- return true;
- }
- break;
- }
- }
- return false;
- }
-
-
///
/// Called when objects or attachments cross the border, or teleport, between regions.
///
@@ -4116,60 +3949,11 @@ namespace OpenSim.Region.Framework.Scenes
{
// CleanDroppedAttachments();
- if (TestBorderCross(acd.startpos, Cardinals.E))
- {
- Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
- acd.startpos.X = crossedBorder.BorderLine.Z - 1;
- }
-
- if (TestBorderCross(acd.startpos, Cardinals.N))
- {
- Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
- acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
- //Mitigate http://opensimulator.org/mantis/view.php?id=3522
- // Check if start position is outside of region
- // If it is, check the Z start position also.. if not, leave it alone.
- if (BordersLocked)
- {
- lock (EastBorders)
- {
- if (acd.startpos.X > EastBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX AGENT POSITION");
- acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- }
- lock (NorthBorders)
- {
- if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX Agent POSITION");
- acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- }
- } else
- {
- if (acd.startpos.X > EastBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX AGENT POSITION");
- acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
- {
- m_log.Warn("FIX Agent POSITION");
- acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
- if (acd.startpos.Z > 720)
- acd.startpos.Z = 720;
- }
- }
+ // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking)
+ if (acd.startpos.X < 0) acd.startpos.X = 1f;
+ if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
+ if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
+ if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
// m_log.DebugFormat(
// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
@@ -4883,44 +4667,6 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence sp = GetScenePresence(remoteClient.AgentId);
if (sp != null)
{
- uint regionX = RegionInfo.RegionLocX;
- uint regionY = RegionInfo.RegionLocY;
-
- Utils.LongToUInts(regionHandle, out regionX, out regionY);
-
- int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
- int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
-
- position.X += shiftx;
- position.Y += shifty;
-
- bool result = false;
-
- if (TestBorderCross(position,Cardinals.N))
- result = true;
-
- if (TestBorderCross(position, Cardinals.S))
- result = true;
-
- if (TestBorderCross(position, Cardinals.E))
- result = true;
-
- if (TestBorderCross(position, Cardinals.W))
- result = true;
-
- // bordercross if position is outside of region
-
- if (!result)
- {
- regionHandle = RegionInfo.RegionHandle;
- }
- else
- {
- // not in this region, undo the shift!
- position.X -= shiftx;
- position.Y -= shifty;
- }
-
if (EntityTransferModule != null)
{
EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 52f46f2f4f..a2625c4a01 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes
public class SceneCommunicationService //one instance per region
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static string LogHeader = "[SCENE COMMUNICATION SERVICE]";
protected RegionInfo m_regionInfo;
protected Scene m_scene;
@@ -100,7 +101,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_log.WarnFormat(
"[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
- m_scene.Name, x / Constants.RegionSize, y / Constants.RegionSize);
+ m_scene.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
}
}
@@ -166,7 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
// we only want to send one update to each simulator; the simulator will
// hand it off to the regions where a child agent exists, this does assume
// that the region position is cached or performance will degrade
- Utils.LongToUInts(regionHandle, out x, out y);
+ Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
if (dest == null)
continue;
@@ -206,7 +207,7 @@ namespace OpenSim.Region.Framework.Scenes
//m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
uint x = 0, y = 0;
- Utils.LongToUInts(regionHandle, out x, out y);
+ Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
@@ -226,6 +227,8 @@ namespace OpenSim.Region.Framework.Scenes
{
foreach (ulong handle in regionslst)
{
+ // We must take a copy here since handle acts like a reference when used in an iterator.
+ // This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region.
ulong handleCopy = handle;
Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 89c7a1a3e1..cb2f377e32 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -412,7 +412,7 @@ namespace OpenSim.Region.Framework.Scenes
{
get
{
- Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
+ Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
Vector3 maxScale = Vector3.Zero;
Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
@@ -529,12 +529,10 @@ namespace OpenSim.Region.Framework.Scenes
set
{
Vector3 val = value;
- if (Scene != null && !IsAttachmentCheckFull()
- && !Scene.LoadingPrims &&
- (Scene.TestBorderCross(val, Cardinals.E) ||
- Scene.TestBorderCross(val, Cardinals.W) ||
- Scene.TestBorderCross(val, Cardinals.N) ||
- Scene.TestBorderCross(val, Cardinals.S))
+ if (Scene != null
+ && Scene.PositionIsInCurrentRegion(val)
+ && !IsAttachmentCheckFull()
+ && !Scene.LoadingPrims
)
{
if (!inTransit)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 91293c4ad8..897965913d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2979,10 +2979,7 @@ namespace OpenSim.Region.Framework.Scenes
{
Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
- if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
- || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
- || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
- || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
+ if (!ParentGroup.Scene.PositionIsInCurrentRegion(newpos))
{
ParentGroup.AbsolutePosition = newpos;
return;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index dff582b8c3..3e278a917b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -842,9 +842,8 @@ namespace OpenSim.Region.Framework.Scenes
foreach (ulong handle in seeds.Keys)
{
uint x, y;
- Utils.LongToUInts(handle, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(handle, out x, out y);
+
if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
{
old.Add(handle);
@@ -866,9 +865,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (KeyValuePair kvp in KnownRegions)
{
uint x, y;
- Utils.LongToUInts(kvp.Key, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
}
}
@@ -1170,18 +1167,6 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentID == 0)
{
- if (m_scene.TestBorderCross(pos, Cardinals.E))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
- pos.X = crossedBorder.BorderLine.Z - 1;
- }
-
- if (m_scene.TestBorderCross(pos, Cardinals.N))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
- pos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
CheckAndAdjustLandingPoint(ref pos);
if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -1201,7 +1186,7 @@ namespace OpenSim.Region.Framework.Scenes
float posZLimit = 0;
- if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
+ if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
float newPosZ = posZLimit + localAVHeight / 2;
@@ -2612,7 +2597,7 @@ namespace OpenSim.Region.Framework.Scenes
if (regionCombinerModule != null)
regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
else
- regionSize = new Vector2(Constants.RegionSize);
+ regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
if (pos.X < 0 || pos.X >= regionSize.X
|| pos.Y < 0 || pos.Y >= regionSize.Y
@@ -2630,8 +2615,8 @@ namespace OpenSim.Region.Framework.Scenes
// }
// Get terrain height for sub-region in a megaregion if necessary
- int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
- int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
+ int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
+ int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
// If X and Y is NaN, target_region will be null
if (target_region == null)
@@ -2642,7 +2627,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
targetScene = m_scene;
- float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
+ float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
// dont try to land underground
terrainHeight += Appearance.AvatarHeight / 2;
pos.Z = Math.Max(terrainHeight, pos.Z);
@@ -3872,32 +3857,28 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat(
// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
// pos2, Name, Scene.Name);
-
- if( Scene.TestBorderCross(pos2, Cardinals.E) ||
- Scene.TestBorderCross(pos2, Cardinals.W) ||
- Scene.TestBorderCross(pos2, Cardinals.N) ||
- Scene.TestBorderCross(pos2, Cardinals.S)
- )
+
+ if (Scene.PositionIsInCurrentRegion(pos2))
+ return;
+
+ if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
{
- if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
- {
- // we don't have entity transfer module
- Vector3 pos = AbsolutePosition;
- float px = pos.X;
- if (px < 0)
- pos.X += Velocity.X * 2;
- else if (px > m_scene.RegionInfo.RegionSizeX)
- pos.X -= Velocity.X * 2;
+ // we don't have entity transfer module
+ Vector3 pos = AbsolutePosition;
+ float px = pos.X;
+ if (px < 0)
+ pos.X += Velocity.X * 2;
+ else if (px > m_scene.RegionInfo.RegionSizeX)
+ pos.X -= Velocity.X * 2;
- float py = pos.Y;
- if (py < 0)
- pos.Y += Velocity.Y * 2;
- else if (py > m_scene.RegionInfo.RegionSizeY)
- pos.Y -= Velocity.Y * 2;
+ float py = pos.Y;
+ if (py < 0)
+ pos.Y += Velocity.Y * 2;
+ else if (py > m_scene.RegionInfo.RegionSizeY)
+ pos.Y -= Velocity.Y * 2;
- Velocity = Vector3.Zero;
- AbsolutePosition = pos;
- }
+ Velocity = Vector3.Zero;
+ AbsolutePosition = pos;
}
}
@@ -3962,7 +3943,7 @@ namespace OpenSim.Region.Framework.Scenes
// Put the child agent back at the center
AbsolutePosition
- = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
+ = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
Animator.ResetAnimations();
}
@@ -3989,9 +3970,7 @@ namespace OpenSim.Region.Framework.Scenes
if (handle != Scene.RegionInfo.RegionHandle)
{
uint x, y;
- Utils.LongToUInts(handle, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(handle, out x, out y);
// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index b6e0a97fce..3d563a6523 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -25,13 +25,20 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using System;
+using System.IO;
+using System.Text;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Serialization;
+
+using OpenSim.Data;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
-using System;
-using System.Text;
-using System.Xml;
-using System.IO;
-using System.Xml.Serialization;
+
+using OpenMetaverse;
+
+using log4net;
namespace OpenSim.Region.Framework.Scenes
{
@@ -40,140 +47,136 @@ namespace OpenSim.Region.Framework.Scenes
///
public class TerrainChannel : ITerrainChannel
{
- private readonly bool[,] taint;
- private double[,] map;
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static string LogHeader = "[TERRAIN CHANNEL]";
+ protected TerrainData m_terrainData;
+
+ public int Width { get { return m_terrainData.SizeX; } } // X dimension
+ // Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
+ public int Height { get { return m_terrainData.SizeY; } } // Y dimension
+ public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
+
+ // Default, not-often-used builder
public TerrainChannel()
{
- map = new double[Constants.RegionSize, Constants.RegionSize];
- taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16];
-
- PinHeadIsland();
+ m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
+ FlatLand();
+ // PinHeadIsland();
}
- public TerrainChannel(String type)
+ // Create terrain of given size
+ public TerrainChannel(int pX, int pY)
{
- map = new double[Constants.RegionSize, Constants.RegionSize];
- taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16];
+ m_terrainData = new HeightmapTerrainData(pX, pY, (int)Constants.RegionHeight);
+ }
+ // Create terrain of specified size and initialize with specified terrain.
+ // TODO: join this with the terrain initializers.
+ public TerrainChannel(String type, int pX, int pY, int pZ)
+ {
+ m_terrainData = new HeightmapTerrainData(pX, pY, pZ);
if (type.Equals("flat"))
FlatLand();
else
PinHeadIsland();
}
- public TerrainChannel(double[,] import)
+ // Create channel passed a heightmap and expected dimensions of the region.
+ // The heightmap might not fit the passed size so accomodations must be made.
+ public TerrainChannel(double[,] pM, int pSizeX, int pSizeY, int pAltitude)
{
- map = import;
- taint = new bool[import.GetLength(0),import.GetLength(1)];
+ int hmSizeX = pM.GetLength(0);
+ int hmSizeY = pM.GetLength(1);
+
+ m_terrainData = new HeightmapTerrainData(pSizeX, pSizeY, pAltitude);
+
+ for (int xx = 0; xx < pSizeX; xx++)
+ for (int yy = 0; yy < pSizeY; yy++)
+ if (xx > hmSizeX || yy > hmSizeY)
+ m_terrainData[xx, yy] = TerrainData.DefaultTerrainHeight;
+ else
+ m_terrainData[xx, yy] = (float)pM[xx, yy];
}
- public TerrainChannel(bool createMap)
+ public TerrainChannel(TerrainData pTerrData)
{
- if (createMap)
- {
- map = new double[Constants.RegionSize,Constants.RegionSize];
- taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16];
- }
- }
-
- public TerrainChannel(int w, int h)
- {
- map = new double[w,h];
- taint = new bool[w / 16,h / 16];
+ m_terrainData = pTerrData;
}
#region ITerrainChannel Members
- public int Width
- {
- get { return map.GetLength(0); }
- }
-
- public int Height
- {
- get { return map.GetLength(1); }
- }
-
+ // ITerrainChannel.MakeCopy()
public ITerrainChannel MakeCopy()
{
- TerrainChannel copy = new TerrainChannel(false);
- copy.map = (double[,]) map.Clone();
-
- return copy;
+ return this.Copy();
}
+ // ITerrainChannel.GetTerrainData()
+ public TerrainData GetTerrainData()
+ {
+ return m_terrainData;
+ }
+
+ // ITerrainChannel.GetFloatsSerialized()
+ // This one dimensional version is ordered so height = map[y*sizeX+x];
+ // DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
+ // and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
public float[] GetFloatsSerialised()
{
- // Move the member variables into local variables, calling
- // member variables 256*256 times gets expensive
- int w = Width;
- int h = Height;
- float[] heights = new float[w * h];
+ return m_terrainData.GetFloatsSerialized();
+ }
+
+ // ITerrainChannel.GetDoubles()
+ public double[,] GetDoubles()
+ {
+ double[,] heights = new double[Width, Height];
- int i, j; // map coordinates
int idx = 0; // index into serialized array
- for (i = 0; i < h; i++)
+ for (int ii = 0; ii < Width; ii++)
{
- for (j = 0; j < w; j++)
+ for (int jj = 0; jj < Height; jj++)
{
- heights[idx++] = (float)map[j, i];
+ heights[ii, jj] = (double)m_terrainData[ii, jj];
+ idx++;
}
}
return heights;
}
- public double[,] GetDoubles()
- {
- return map;
- }
-
+ // ITerrainChannel.this[x,y]
public double this[int x, int y]
{
- get
- {
- if (x < 0) x = 0;
- if (y < 0) y = 0;
- if (x >= (int)Constants.RegionSize) x = (int)Constants.RegionSize - 1;
- if (y >= (int)Constants.RegionSize) y = (int)Constants.RegionSize - 1;
-
- return map[x, y];
+ get {
+ if (x < 0 || x >= Width || y < 0 || y >= Height)
+ return 0;
+ return (double)m_terrainData[x, y];
}
set
{
- // Will "fix" terrain hole problems. Although not fantastically.
if (Double.IsNaN(value) || Double.IsInfinity(value))
return;
- if (map[x, y] != value)
- {
- taint[x / 16, y / 16] = true;
- map[x, y] = value;
- }
+ m_terrainData[x, y] = (float)value;
}
}
+ // ITerrainChannel.GetHieghtAtXYZ(x, y, z)
+ public float GetHeightAtXYZ(float x, float y, float z)
+ {
+ if (x < 0 || x >= Width || y < 0 || y >= Height)
+ return 0;
+ return m_terrainData[(int)x, (int)y];
+ }
+
+ // ITerrainChannel.Tainted()
public bool Tainted(int x, int y)
{
- if (taint[x / 16, y / 16])
- {
- taint[x / 16, y / 16] = false;
- return true;
- }
- return false;
- }
-
- #endregion
-
- public TerrainChannel Copy()
- {
- TerrainChannel copy = new TerrainChannel(false);
- copy.map = (double[,]) map.Clone();
-
- return copy;
+ return m_terrainData.IsTaintedAt(x, y);
}
+ // ITerrainChannel.SaveToXmlString()
public string SaveToXmlString()
{
XmlWriterSettings settings = new XmlWriterSettings();
@@ -189,13 +192,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- private void WriteXml(XmlWriter writer)
- {
- writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
- ToXml(writer);
- writer.WriteEndElement();
- }
-
+ // ITerrainChannel.LoadFromXmlString()
public void LoadFromXmlString(string data)
{
StringReader sr = new StringReader(data);
@@ -207,12 +204,124 @@ namespace OpenSim.Region.Framework.Scenes
sr.Close();
}
- private void ReadXml(XmlReader reader)
+ // ITerrainChannel.Merge
+ public void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement)
{
- reader.ReadStartElement("TerrainMap");
- FromXml(reader);
+ m_log.DebugFormat("{0} Merge. inSize=<{1},{2}>, disp={3}, rot={4}, rotDisp={5}, outSize=<{6},{7}>", LogHeader,
+ newTerrain.Width, newTerrain.Height,
+ displacement, radianRotation, rotationDisplacement,
+ m_terrainData.SizeX, m_terrainData.SizeY);
+ for (int xx = 0; xx < newTerrain.Width; xx++)
+ {
+ for (int yy = 0; yy < newTerrain.Height; yy++)
+ {
+ int dispX = (int)displacement.X;
+ int dispY = (int)displacement.Y;
+ float newHeight = (float)newTerrain[xx, yy] + displacement.Z;
+ if (radianRotation == 0)
+ {
+ // If no rotation, place the new height in the specified location
+ dispX += xx;
+ dispY += yy;
+ if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
+ {
+ m_terrainData[dispX, dispY] = newHeight;
+ }
+ }
+ else
+ {
+ // If rotating, we have to smooth the result because the conversion
+ // to ints will mean heightmap entries will not get changed
+ // First compute the rotation location for the new height.
+ dispX += (int)(rotationDisplacement.X
+ + ((float)xx - rotationDisplacement.X) * Math.Cos(radianRotation)
+ - ((float)yy - rotationDisplacement.Y) * Math.Sin(radianRotation) );
+
+ dispY += (int)(rotationDisplacement.Y
+ + ((float)xx - rotationDisplacement.X) * Math.Sin(radianRotation)
+ + ((float)yy - rotationDisplacement.Y) * Math.Cos(radianRotation) );
+
+ if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
+ {
+ float oldHeight = m_terrainData[dispX, dispY];
+ // Smooth the heights around this location if the old height is far from this one
+ for (int sxx = dispX - 2; sxx < dispX + 2; sxx++)
+ {
+ for (int syy = dispY - 2; syy < dispY + 2; syy++)
+ {
+ if (sxx >= 0 && sxx < m_terrainData.SizeX && syy >= 0 && syy < m_terrainData.SizeY)
+ {
+ if (sxx == dispX && syy == dispY)
+ {
+ // Set height for the exact rotated point
+ m_terrainData[dispX, dispY] = newHeight;
+ }
+ else
+ {
+ if (Math.Abs(m_terrainData[sxx, syy] - newHeight) > 1f)
+ {
+ // If the adjacent height is far off, force it to this height
+ m_terrainData[sxx, syy] = newHeight;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
+ {
+ m_terrainData[dispX, dispY] = (float)newTerrain[xx, yy];
+ }
+ }
+ }
+ }
}
+ #endregion
+
+ public TerrainChannel Copy()
+ {
+ TerrainChannel copy = new TerrainChannel();
+ copy.m_terrainData = m_terrainData.Clone();
+ return copy;
+ }
+
+ private void WriteXml(XmlWriter writer)
+ {
+ if (Width == Constants.RegionSize && Height == Constants.RegionSize)
+ {
+ // Downward compatibility for legacy region terrain maps.
+ // If region is exactly legacy size, return the old format XML.
+ writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
+ ToXml(writer);
+ writer.WriteEndElement();
+ }
+ else
+ {
+ // New format XML that includes width and length.
+ writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
+ ToXml2(writer);
+ writer.WriteEndElement();
+ }
+ }
+
+ private void ReadXml(XmlReader reader)
+ {
+ // Check the first element. If legacy element, use the legacy reader.
+ if (reader.IsStartElement("TerrainMap"))
+ {
+ reader.ReadStartElement("TerrainMap");
+ FromXml(reader);
+ }
+ else
+ {
+ reader.ReadStartElement("TerrainMap2");
+ FromXml2(reader);
+ }
+ }
+
+ // Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
private void ToXml(XmlWriter xmlWriter)
{
float[] mapData = GetFloatsSerialised();
@@ -226,12 +335,15 @@ namespace OpenSim.Region.Framework.Scenes
serializer.Serialize(xmlWriter, buffer);
}
+ // Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
private void FromXml(XmlReader xmlReader)
{
XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
int index = 0;
+ m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight);
+
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
@@ -244,35 +356,63 @@ namespace OpenSim.Region.Framework.Scenes
}
}
+ private class TerrainChannelXMLPackage
+ {
+ public int Version;
+ public int SizeX;
+ public int SizeY;
+ public int SizeZ;
+ public float CompressionFactor;
+ public int[] Map;
+ public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap)
+ {
+ Version = 1;
+ SizeX = pX;
+ SizeY = pY;
+ SizeZ = pZ;
+ CompressionFactor = pCompressionFactor;
+ Map = pMap;
+ }
+ }
+
+ // New terrain serialization format that includes the width and length.
+ private void ToXml2(XmlWriter xmlWriter)
+ {
+ TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
+ m_terrainData.GetCompressedMap());
+ XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
+ serializer.Serialize(xmlWriter, package);
+ }
+
+ // New terrain serialization format that includes the width and length.
+ private void FromXml2(XmlReader xmlReader)
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
+ TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
+ m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
+ }
+
+ // Fill the heightmap with the center bump terrain
private void PinHeadIsland()
{
- int x;
- for (x = 0; x < Constants.RegionSize; x++)
+ for (int x = 0; x < Width; x++)
{
- int y;
- for (y = 0; y < Constants.RegionSize; y++)
+ for (int y = 0; y < Height; y++)
{
- map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
- double spherFacA = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01;
- double spherFacB = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001;
- if (map[x, y] < spherFacA)
- map[x, y] = spherFacA;
- if (map[x, y] < spherFacB)
- map[x, y] = spherFacB;
+ m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
+ float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d);
+ float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d);
+ if (m_terrainData[x, y]< spherFacA)
+ m_terrainData[x, y]= spherFacA;
+ if (m_terrainData[x, y]< spherFacB)
+ m_terrainData[x, y] = spherFacB;
}
}
}
private void FlatLand()
{
- int x;
- for (x = 0; x < Constants.RegionSize; x++)
- {
- int y;
- for (y = 0; y < Constants.RegionSize; y++)
- map[x, y] = 21;
- }
+ m_terrainData.ClearLand();
}
-
}
}
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
new file mode 100644
index 0000000000..fc8f8cd2c5
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -0,0 +1,948 @@
+/*
+ * 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.
+ */
+
+/* Freely adapted from the Aurora version of the terrain compressor.
+ * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
+ */
+
+using System;
+using System.Reflection;
+
+using log4net;
+
+using OpenSim.Framework;
+using OpenSim.Region.Framework;
+using OpenSim.Region.Framework.Scenes;
+
+using OpenMetaverse;
+using OpenMetaverse.Packets;
+
+namespace OpenSim.Region.ClientStack.LindenUDP
+{
+ public static class OpenSimTerrainCompressor
+ {
+// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+#pragma warning disable 414
+ private static string LogHeader = "[TERRAIN COMPRESSOR]";
+#pragma warning restore 414
+
+ public const int END_OF_PATCHES = 97;
+
+ private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
+ private const int STRIDE = 264;
+
+ private const int ZERO_CODE = 0x0;
+ private const int ZERO_EOB = 0x2;
+ private const int POSITIVE_VALUE = 0x6;
+ private const int NEGATIVE_VALUE = 0x7;
+
+ private static readonly float[] DequantizeTable16 =
+ new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+ private static readonly float[] DequantizeTable32 =
+ new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+ private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ //private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
+ private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+ private static readonly float[] QuantizeTable16 =
+ new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+ static OpenSimTerrainCompressor()
+ {
+ // Initialize the decompression tables
+ BuildDequantizeTable16();
+ SetupCosines16();
+ BuildCopyMatrix16();
+ BuildQuantizeTable16();
+ }
+
+ // Used to send cloud and wind patches
+ public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX,
+ int pRegionSizeY)
+ {
+ LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
+
+ TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
+ {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
+
+ // Should be enough to fit even the most poorly packed data
+ byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2];
+ BitPack bitpack = new BitPack(data, 0);
+ bitpack.PackBits(header.Stride, 16);
+ bitpack.PackBits(header.PatchSize, 8);
+ bitpack.PackBits(type, 8);
+
+ foreach (TerrainPatch t in patches)
+ CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY);
+
+ bitpack.PackBits(END_OF_PATCHES, 8);
+
+ layer.LayerData.Data = new byte[bitpack.BytePos + 1];
+ Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
+
+ return layer;
+ }
+
+ // Create a land packet for a single patch.
+ public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
+ {
+ int[] xPieces = new int[1];
+ int[] yPieces = new int[1];
+ xPieces[0] = patchX; // patch X dimension
+ yPieces[0] = patchY;
+
+ return CreateLandPacket(terrData, xPieces, yPieces);
+ }
+
+ public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] xPieces, int[] yPieces)
+ {
+ byte landPacketType = (byte)TerrainPatch.LayerType.Land;
+ if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
+ {
+ landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
+ }
+
+ return CreateLandPacket(terrData, xPieces, yPieces, landPacketType);
+ }
+
+ ///
+ /// Creates a LayerData packet for compressed land data given a full
+ /// simulator heightmap and an array of indices of patches to compress
+ ///
+ ///
+ /// Terrain data that can result in a meter square heightmap.
+ ///
+ ///
+ /// Array of indexes in the grid of patches
+ /// for this simulator.
+ /// If creating a packet for multiple patches, there will be entries in
+ /// both the X and Y arrays for each of the patches.
+ /// For example if patches 1 and 17 are to be sent,
+ /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
+ /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
+ ///
+ ///
+ /// Array of indexes in the grid of patches.
+ ///
+ ///
+ ///
+ public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
+ {
+ LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
+
+ TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
+ {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
+
+ byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
+ BitPack bitpack = new BitPack(data, 0);
+ bitpack.PackBits(header.Stride, 16);
+ bitpack.PackBits(header.PatchSize, 8);
+ bitpack.PackBits(type, 8);
+
+ for (int i = 0; i < x.Length; i++)
+ CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]);
+
+ bitpack.PackBits(END_OF_PATCHES, 8);
+
+ layer.LayerData.Data = new byte[bitpack.BytePos + 1];
+ Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
+
+ return layer;
+ }
+
+ // Unused: left for historical reference.
+ public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY)
+ {
+ TerrainPatch.Header header = PrescanPatch(patchData);
+ header.QuantWBits = 136;
+ if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
+ {
+ header.PatchIDs = (y & 0xFFFF);
+ header.PatchIDs += (x << 16);
+ }
+ else
+ {
+ header.PatchIDs = (y & 0x1F);
+ header.PatchIDs += (x << 5);
+ }
+
+ // NOTE: No idea what prequant and postquant should be or what they do
+
+ int wbits;
+ int[] patch = CompressPatch(patchData, header, 10, out wbits);
+ wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits);
+ EncodePatch(output, patch, 0, wbits);
+ }
+
+ ///
+ /// Add a patch of terrain to a BitPacker
+ ///
+ /// BitPacker to write the patch to
+ ///
+ /// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
+ ///
+ ///
+ /// X offset of the patch to create.
+ ///
+ ///
+ /// Y offset of the patch to create.
+ ///
+ ///
+ ///
+ public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
+ {
+ TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY);
+ header.QuantWBits = 136;
+
+ // If larger than legacy region size, pack patch X and Y info differently.
+ if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
+ {
+ header.PatchIDs = (patchY & 0xFFFF);
+ header.PatchIDs += (patchX << 16);
+ }
+ else
+ {
+ header.PatchIDs = (patchY & 0x1F);
+ header.PatchIDs += (patchX << 5);
+ }
+
+ // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}",
+ // LogHeader, patchX, patchY, header.DCOffset, header.Range);
+
+ // NOTE: No idea what prequant and postquant should be or what they do
+ int wbits;
+ int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
+ wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
+ EncodePatch(output, patch, 0, wbits);
+ }
+
+ private static TerrainPatch.Header PrescanPatch(float[] patch)
+ {
+ TerrainPatch.Header header = new TerrainPatch.Header();
+ float zmax = -99999999.0f;
+ float zmin = 99999999.0f;
+
+ for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
+ {
+ float val = patch[i];
+ if (val > zmax) zmax = val;
+ if (val < zmin) zmin = val;
+ }
+
+ header.DCOffset = zmin;
+ header.Range = (int) ((zmax - zmin) + 1.0f);
+
+ return header;
+ }
+
+ // Scan the height info we're returning and return a patch packet header for this patch.
+ private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY)
+ {
+ TerrainPatch.Header header = new TerrainPatch.Header();
+ float zmax = -99999999.0f;
+ float zmin = 99999999.0f;
+
+ for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++)
+ {
+ for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++)
+ {
+ float val = terrData[i, j];
+ if (val > zmax) zmax = val;
+ if (val < zmin) zmin = val;
+ }
+ }
+
+ header.DCOffset = zmin;
+ header.Range = (int)((zmax - zmin) + 1.0f);
+
+ return header;
+ }
+
+ public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
+ {
+ TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
+
+ // Quantized word bits
+ if (header.QuantWBits == END_OF_PATCHES)
+ return header;
+
+ // DC offset
+ header.DCOffset = bitpack.UnpackFloat();
+
+ // Range
+ header.Range = bitpack.UnpackBits(16);
+
+ // Patch IDs (10 bits)
+ header.PatchIDs = bitpack.UnpackBits(10);
+
+ // Word bits
+ header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
+
+ return header;
+ }
+
+ private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX,
+ uint pRegionSizeY, int wbits)
+ {
+ /*
+ int temp;
+ int wbits = (header.QuantWBits & 0x0f) + 2;
+ uint maxWbits = (uint)wbits + 5;
+ uint minWbits = ((uint)wbits >> 1);
+ int wbitsMaxValue;
+ */
+ // goal is to determ minimum number of bits to use so all data fits
+ /*
+ wbits = (int)minWbits;
+ wbitsMaxValue = (1 << wbits);
+
+ for (int i = 0; i < patch.Length; i++)
+ {
+ temp = patch[i];
+ if (temp != 0)
+ {
+ // Get the absolute value
+ if (temp < 0) temp *= -1;
+
+ no coments..
+
+ for (int j = (int)maxWbits; j > (int)minWbits; j--)
+ {
+ if ((temp & (1 << j)) != 0)
+ {
+ if (j > wbits) wbits = j;
+ break;
+ }
+ }
+
+ while (temp > wbitsMaxValue)
+ {
+ wbits++;
+ if (wbits == maxWbits)
+ goto Done;
+ wbitsMaxValue = 1 << wbits;
+ }
+ }
+ }
+
+ Done:
+
+ // wbits += 1;
+ */
+ // better check
+ if (wbits > 17)
+ wbits = 16;
+ else if (wbits < 3)
+ wbits = 3;
+
+ header.QuantWBits &= 0xf0;
+
+ header.QuantWBits |= (wbits - 2);
+
+ output.PackBits(header.QuantWBits, 8);
+ output.PackFloat(header.DCOffset);
+ output.PackBits(header.Range, 16);
+ if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
+ output.PackBits(header.PatchIDs, 32);
+ else
+ output.PackBits(header.PatchIDs, 10);
+
+ return wbits;
+ }
+
+ private static void IDCTColumn16(float[] linein, float[] lineout, int column)
+ {
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ float total = OO_SQRT2*linein[column];
+
+ for (int u = 1; u < Constants.TerrainPatchSize; u++)
+ {
+ int usize = u*Constants.TerrainPatchSize;
+ total += linein[usize + column]*CosineTable16[usize + n];
+ }
+
+ lineout[Constants.TerrainPatchSize*n + column] = total;
+ }
+ }
+
+ private static void IDCTLine16(float[] linein, float[] lineout, int line)
+ {
+ const float oosob = 2.0f/Constants.TerrainPatchSize;
+ int lineSize = line*Constants.TerrainPatchSize;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ float total = OO_SQRT2*linein[lineSize];
+
+ for (int u = 1; u < Constants.TerrainPatchSize; u++)
+ {
+ total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n];
+ }
+
+ lineout[lineSize + n] = total*oosob;
+ }
+ }
+
+/*
+ private static void DCTLine16(float[] linein, float[] lineout, int line)
+ {
+ float total = 0.0f;
+ int lineSize = line * Constants.TerrainPatchSize;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ total += linein[lineSize + n];
+ }
+
+ lineout[lineSize] = OO_SQRT2 * total;
+
+ int uptr = 0;
+ for (int u = 1; u < Constants.TerrainPatchSize; u++)
+ {
+ total = 0.0f;
+ uptr += Constants.TerrainPatchSize;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ total += linein[lineSize + n] * CosineTable16[uptr + n];
+ }
+
+ lineout[lineSize + u] = total;
+ }
+ }
+*/
+
+ private static void DCTLine16(float[] linein, float[] lineout, int line)
+ {
+ // outputs transpose data (lines exchanged with coluns )
+ // so to save a bit of cpu when doing coluns
+ float total = 0.0f;
+ int lineSize = line*Constants.TerrainPatchSize;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ total += linein[lineSize + n];
+ }
+
+ lineout[line] = OO_SQRT2*total;
+
+ for (int u = Constants.TerrainPatchSize;
+ u < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
+ u += Constants.TerrainPatchSize)
+ {
+ total = 0.0f;
+ for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
+ {
+ total += linein[ptrn]*CosineTable16[ptru];
+ }
+
+ lineout[line + u] = total;
+ }
+ }
+
+
+ /*
+ private static void DCTColumn16(float[] linein, int[] lineout, int column)
+ {
+ float total = 0.0f;
+ // const float oosob = 2.0f / Constants.TerrainPatchSize;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ total += linein[Constants.TerrainPatchSize * n + column];
+ }
+
+ // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
+ lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
+
+ for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize)
+ {
+ total = 0.0f;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
+ }
+
+ // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
+ lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]);
+ }
+ }
+
+ private static void DCTColumn16(float[] linein, int[] lineout, int column)
+ {
+ // input columns are in fact stored in lines now
+
+ float total = 0.0f;
+// const float oosob = 2.0f / Constants.TerrainPatchSize;
+ int inlinesptr = Constants.TerrainPatchSize*column;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ total += linein[inlinesptr + n];
+ }
+
+ // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
+ lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
+
+ for (int uptr = Constants.TerrainPatchSize;
+ uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
+ uptr += Constants.TerrainPatchSize)
+ {
+ total = 0.0f;
+
+ for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
+ {
+ total += linein[n]*CosineTable16[ptru];
+ }
+
+// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
+ lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]);
+ }
+ }
+ */
+
+ private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits)
+ {
+ // input columns are in fact stored in lines now
+
+ bool dowbits = wbits != maxwbits;
+ int wbitsMaxValue = 1 << wbits;
+
+ float total = 0.0f;
+ // const float oosob = 2.0f / Constants.TerrainPatchSize;
+ int inlinesptr = Constants.TerrainPatchSize*column;
+
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ total += linein[inlinesptr + n];
+ }
+
+ // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
+ int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
+ lineout[CopyMatrix16[column]] = tmp;
+
+ if (dowbits)
+ {
+ if (tmp < 0) tmp *= -1;
+ while (tmp > wbitsMaxValue)
+ {
+ wbits++;
+ wbitsMaxValue = 1 << wbits;
+ if (wbits == maxwbits)
+ {
+ dowbits = false;
+ break;
+ }
+ }
+ }
+
+ for (int uptr = Constants.TerrainPatchSize;
+ uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
+ uptr += Constants.TerrainPatchSize)
+ {
+ total = 0.0f;
+
+ for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
+ {
+ total += linein[n]*CosineTable16[ptru];
+ }
+
+ tmp = (int) (total*QuantizeTable16[uptr + column]);
+ lineout[CopyMatrix16[uptr + column]] = tmp;
+
+ if (dowbits)
+ {
+ if (tmp < 0) tmp *= -1;
+ while (tmp > wbitsMaxValue)
+ {
+ wbits++;
+ wbitsMaxValue = 1 << wbits;
+ if (wbits == maxwbits)
+ {
+ dowbits = false;
+ break;
+ }
+ }
+ }
+ }
+ return wbits;
+ }
+
+ public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
+ {
+ for (int n = 0; n < size*size; n++)
+ {
+ // ?
+ int temp = bitpack.UnpackBits(1);
+ if (temp != 0)
+ {
+ // Value or EOB
+ temp = bitpack.UnpackBits(1);
+ if (temp != 0)
+ {
+ // Value
+ temp = bitpack.UnpackBits(1);
+ if (temp != 0)
+ {
+ // Negative
+ temp = bitpack.UnpackBits((int) header.WordBits);
+ patches[n] = temp*-1;
+ }
+ else
+ {
+ // Positive
+ temp = bitpack.UnpackBits((int) header.WordBits);
+ patches[n] = temp;
+ }
+ }
+ else
+ {
+ // Set the rest to zero
+ // TODO: This might not be necessary
+ for (int o = n; o < size*size; o++)
+ {
+ patches[o] = 0;
+ }
+ break;
+ }
+ }
+ else
+ {
+ patches[n] = 0;
+ }
+ }
+ }
+
+ private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
+ {
+ int maxwbitssize = (1 << wbits) - 1;
+
+ if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0)
+ {
+ Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
+ return;
+ }
+
+ if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0;
+
+ for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
+ {
+ int temp = patch[i];
+
+ if (temp == 0)
+ {
+ bool eob = true;
+
+ for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
+ {
+ if (patch[j] != 0)
+ {
+ eob = false;
+ break;
+ }
+ }
+
+ if (eob)
+ {
+ output.PackBits(ZERO_EOB, 2);
+ return;
+ }
+ output.PackBits(ZERO_CODE, 1);
+ }
+ else
+ {
+ if (temp < 0)
+ {
+ temp *= -1;
+
+ if (temp > maxwbitssize) temp = maxwbitssize;
+
+ output.PackBits(NEGATIVE_VALUE, 3);
+ output.PackBits(temp, wbits);
+ }
+ else
+ {
+ if (temp > maxwbitssize) temp = maxwbitssize;
+
+ output.PackBits(POSITIVE_VALUE, 3);
+ output.PackBits(temp, wbits);
+ }
+ }
+ }
+ }
+
+ public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group)
+ {
+ float[] block = new float[group.PatchSize*group.PatchSize];
+ float[] output = new float[group.PatchSize*group.PatchSize];
+ int prequant = (header.QuantWBits >> 4) + 2;
+ int quantize = 1 << prequant;
+ float ooq = 1.0f/quantize;
+ float mult = ooq*header.Range;
+ float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
+
+ if (group.PatchSize == Constants.TerrainPatchSize)
+ {
+ for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
+ {
+ block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n];
+ }
+
+ float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ IDCTColumn16(block, ftemp, o);
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ IDCTLine16(ftemp, block, o);
+ }
+ else
+ {
+ for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
+ {
+ block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n];
+ }
+
+ Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error);
+ }
+
+ for (int j = 0; j < block.Length; j++)
+ {
+ output[j] = block[j]*mult + addval;
+ }
+
+ return output;
+ }
+
+ private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
+ {
+ float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ int wordsize = (prequant - 2) & 0x0f;
+ float oozrange = 1.0f/header.Range;
+ float range = (1 << prequant);
+ float premult = oozrange*range;
+ float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
+
+ header.QuantWBits = wordsize;
+ header.QuantWBits |= wordsize << 4;
+
+ int k = 0;
+ for (int j = 0; j < Constants.TerrainPatchSize; j++)
+ {
+ for (int i = 0; i < Constants.TerrainPatchSize; i++)
+ block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub;
+ }
+
+ float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+
+ int maxWbits = prequant + 5;
+ wbits = (prequant >> 1);
+
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ DCTLine16(block, ftemp, o);
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
+
+ return itemp;
+ }
+
+ private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits)
+ {
+ float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ float oozrange = 1.0f/header.Range;
+ float range = (1 << prequant);
+ float premult = oozrange*range;
+ float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
+ int wordsize = (prequant - 2) & 0x0f;
+
+ header.QuantWBits = wordsize;
+ header.QuantWBits |= wordsize << 4;
+
+ int k = 0;
+ for (int j = 0; j < Constants.TerrainPatchSize; j++)
+ {
+ for (int i = 0; i < Constants.TerrainPatchSize; i++)
+ block[k++] = patchData[j, i]*premult - sub;
+ }
+
+ float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+ int maxWbits = prequant + 5;
+ wbits = (prequant >> 1);
+
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ DCTLine16(block, ftemp, o);
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
+
+ return itemp;
+ }
+
+ private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
+ int prequant, out int wbits)
+ {
+ float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ int wordsize = prequant;
+ float oozrange = 1.0f/header.Range;
+ float range = (1 << prequant);
+ float premult = oozrange*range;
+ float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
+
+ header.QuantWBits = wordsize - 2;
+ header.QuantWBits |= (prequant - 2) << 4;
+
+ int k = 0;
+
+ int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ?
+ (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY;
+ yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
+
+ int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ?
+ (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX;
+ xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize;
+
+ for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++)
+ {
+ for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
+ {
+ block[k++] = terrData[xx, yy] * premult - sub;
+ }
+ }
+
+ float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+ int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
+
+ int maxWbits = prequant + 5;
+ wbits = (prequant >> 1);
+
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ DCTLine16(block, ftemp, o);
+ for (int o = 0; o < Constants.TerrainPatchSize; o++)
+ wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
+
+ return itemp;
+ }
+
+ #region Initialization
+
+ private static void BuildDequantizeTable16()
+ {
+ for (int j = 0; j < Constants.TerrainPatchSize; j++)
+ {
+ for (int i = 0; i < Constants.TerrainPatchSize; i++)
+ {
+ DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j);
+ }
+ }
+ }
+
+ private static void BuildQuantizeTable16()
+ {
+ const float oosob = 2.0f/Constants.TerrainPatchSize;
+ for (int j = 0; j < Constants.TerrainPatchSize; j++)
+ {
+ for (int i = 0; i < Constants.TerrainPatchSize; i++)
+ {
+// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j));
+ QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
+ }
+ }
+ }
+
+ private static void SetupCosines16()
+ {
+ const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize;
+
+ for (int u = 0; u < Constants.TerrainPatchSize; u++)
+ {
+ for (int n = 0; n < Constants.TerrainPatchSize; n++)
+ {
+ CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz);
+ }
+ }
+ }
+
+ private static void BuildCopyMatrix16()
+ {
+ bool diag = false;
+ bool right = true;
+ int i = 0;
+ int j = 0;
+ int count = 0;
+
+ while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
+ {
+ CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
+
+ if (!diag)
+ {
+ if (right)
+ {
+ if (i < Constants.TerrainPatchSize - 1) i++;
+ else j++;
+
+ right = false;
+ diag = true;
+ }
+ else
+ {
+ if (j < Constants.TerrainPatchSize - 1) j++;
+ else i++;
+
+ right = true;
+ diag = true;
+ }
+ }
+ else
+ {
+ if (right)
+ {
+ i++;
+ j--;
+ if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
+ }
+ else
+ {
+ i--;
+ j++;
+ if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
+ }
+ }
+ }
+ }
+
+ #endregion Initialization
+ }
+}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 8c0ad75f7e..51ecc8d8f3 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -520,7 +520,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public Vector3 StartPos
{
- get { return new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 50); }
+ get { return new Vector3(m_scene.RegionInfo.RegionSizeX * 0.5f, m_scene.RegionInfo.RegionSizeY * 0.5f, 50f); }
set { }
}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index c5cba8e22c..f5bd44db5f 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -52,6 +52,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
// Local constants
+ // This computation is not the real region center if the region is larger than 256.
+ // This computation isn't fixed because there is not a handle back to the region.
private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
private static readonly char[] CS_SPACE = { ' ' };
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
index d4fe5e0cde..550500113c 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
@@ -44,6 +44,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ // This computation is not the real region center if the region is larger than 256.
+ // This computation isn't fixed because there is not a handle back to the region.
private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
private const int DEBUG_CHANNEL = 2147483647;
diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
index a375da903c..0bf23f1a5d 100644
--- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
+++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
@@ -122,8 +122,8 @@ namespace OpenSim.Region.OptionalModules
private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene)
{
- if (newPoint.X < -1f || newPoint.X > (float)(Constants.RegionSize + 1) ||
- newPoint.Y < -1f || newPoint.Y > (float)(Constants.RegionSize + 1))
+ if (newPoint.X < -1f || newPoint.X > (scene.RegionInfo.RegionSizeX + 1) ||
+ newPoint.Y < -1f || newPoint.Y > (scene.RegionInfo.RegionSizeY) )
return true;
SceneObjectPart obj = scene.GetSceneObjectPart(objectID);
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index eb386fe423..296ab87274 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -170,7 +170,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
c.Channel = m_channelNotify;
c.Message += numScriptsFailed.ToString() + "," + message;
c.Type = ChatTypeEnum.Region;
- c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
+ if (m_scene != null)
+ c.Position = new Vector3((m_scene.RegionInfo.RegionSizeX * 0.5f), (m_scene.RegionInfo.RegionSizeY * 0.5f), 30);
+ else
+ c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
c.Sender = null;
c.SenderUUID = UUID.Zero;
c.Scene = m_scene;
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 29b39e031a..6cbccc034f 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -116,37 +116,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
+ "If teleport is true then some extra teleport debug information is logged.\n"
+ "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
HandleDebugSceneSetCommand);
-
- scene.AddCommand(
- "Regions",
- this, "show borders", "show borders", "Show border information for regions", HandleShowBordersCommand);
- }
-
- private void HandleShowBordersCommand(string module, string[] args)
- {
- StringBuilder sb = new StringBuilder();
- sb.AppendFormat("Borders for {0}:\n", m_scene.Name);
-
- ConsoleDisplayTable cdt = new ConsoleDisplayTable();
- cdt.AddColumn("Cross Direction", 15);
- cdt.AddColumn("Line", 34);
- cdt.AddColumn("Trigger Region", 14);
-
- foreach (Border b in m_scene.NorthBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- foreach (Border b in m_scene.EastBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- foreach (Border b in m_scene.SouthBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- foreach (Border b in m_scene.WestBorders)
- cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
-
- cdt.AddToStringBuilder(sb);
-
- MainConsole.Instance.Output(sb.ToString());
}
private void HandleDebugSceneGetCommand(string module, string[] args)
@@ -263,4 +232,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
}
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index 81448709cf..e4a33827ab 100644
--- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
+++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
@@ -748,8 +748,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
position.X = s_tree.AbsolutePosition.X + (float)randX;
position.Y = s_tree.AbsolutePosition.Y + (float)randY;
- if (position.X <= ((int)Constants.RegionSize - 1) && position.X >= 0 &&
- position.Y <= ((int)Constants.RegionSize - 1) && position.Y >= 0 &&
+ if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 &&
+ position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 &&
Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range)
{
UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
index 0816b7b799..8e405616fa 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
@@ -46,6 +46,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
private List _actors = new List();
private List _prims = new List();
private float[] _heightMap;
+ private Vector3 m_regionExtent;
//protected internal string sceneIdentifier;
@@ -58,6 +59,12 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
public override void Initialise(IMesher meshmerizer, IConfigSource config)
{
+ throw new Exception("Should not be called.");
+ }
+
+ public override void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
+ {
+ m_regionExtent = regionExtent;
}
public override void Dispose() {}
@@ -121,23 +128,23 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
{
actorPosition.Y = 0.1F;
}
- else if (actor.Position.Y >= Constants.RegionSize)
+ else if (actor.Position.Y >= m_regionExtent.Y)
{
- actorPosition.Y = ((int)Constants.RegionSize - 0.1f);
+ actorPosition.Y = (m_regionExtent.Y - 0.1f);
}
if (actor.Position.X < 0)
{
actorPosition.X = 0.1F;
}
- else if (actor.Position.X >= Constants.RegionSize)
+ else if (actor.Position.X >= m_regionExtent.X)
{
- actorPosition.X = ((int)Constants.RegionSize - 0.1f);
+ actorPosition.X = (m_regionExtent.X - 0.1f);
}
float terrainHeight = 0;
if (_heightMap != null)
- terrainHeight = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X];
+ terrainHeight = _heightMap[(int)actor.Position.Y * (int)m_regionExtent.Y + (int)actor.Position.X];
float height = terrainHeight + actor.Size.Z;
diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
index 8ccfda5bc4..d14edfd770 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
@@ -32,6 +32,7 @@ using System.Reflection;
using Nini.Config;
using log4net;
using OpenSim.Framework;
+using OpenMetaverse;
namespace OpenSim.Region.Physics.Manager
{
@@ -59,6 +60,14 @@ namespace OpenSim.Region.Physics.Manager
m_log.Info("[PHYSICS]: Added meshing engine: " + plugHard.GetName());
}
+ // Legacy method for simulators before extent was passed
+ public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName,
+ IConfigSource config, string regionName)
+ {
+ Vector3 extent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
+ return GetPhysicsScene(physEngineName, meshEngineName, config, regionName, extent);
+ }
+
///
/// Get a physics scene for the given physics engine and mesher.
///
@@ -66,7 +75,8 @@ namespace OpenSim.Region.Physics.Manager
///
///
///
- public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName, IConfigSource config, string regionName)
+ public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName,
+ IConfigSource config, string regionName, Vector3 regionExtent)
{
if (String.IsNullOrEmpty(physEngineName))
{
@@ -94,7 +104,7 @@ namespace OpenSim.Region.Physics.Manager
{
m_log.Info("[PHYSICS]: creating " + physEngineName);
PhysicsScene result = _PhysPlugins[physEngineName].GetScene(regionName);
- result.Initialise(meshEngine, config);
+ result.Initialise(meshEngine, config, regionExtent);
return result;
}
else
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index dd9bbc1665..4f4ff0731d 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -132,8 +132,17 @@ namespace OpenSim.Region.Physics.Manager
}
}
+ // Deprecated. Do not use this for new physics engines.
public abstract void Initialise(IMesher meshmerizer, IConfigSource config);
+ // For older physics engines that do not implement non-legacy region sizes.
+ // If the physics engine handles the region extent feature, it overrides this function.
+ public virtual void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
+ {
+ // If not overridden, call the old initialization entry.
+ Initialise(meshmerizer, config);
+ }
+
///
/// Add an avatar
///
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 7127c73c18..341c8f8bd6 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -134,6 +134,49 @@ namespace OpenSim.Region.RegionCombinerModule
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)
@@ -220,27 +263,6 @@ namespace OpenSim.Region.RegionCombinerModule
//
*/
- // Give each region a standard set of non-infinite borders
- Border northBorder = new Border();
- northBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
- northBorder.CrossDirection = Cardinals.N;
- scene.NorthBorders[0] = northBorder;
-
- Border southBorder = new Border();
- southBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
- southBorder.CrossDirection = Cardinals.S;
- scene.SouthBorders[0] = southBorder;
-
- Border eastBorder = new Border();
- eastBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, (int)Constants.RegionSize); //<---
- eastBorder.CrossDirection = Cardinals.E;
- scene.EastBorders[0] = eastBorder;
-
- Border westBorder = new Border();
- westBorder.BorderLine = new Vector3(0, (int)Constants.RegionSize, 0); //--->
- westBorder.CrossDirection = Cardinals.W;
- scene.WestBorders[0] = westBorder;
-
RegionConnections newConn = new RegionConnections();
newConn.ConnectedRegions = new List();
newConn.RegionScene = scene;
@@ -248,8 +270,8 @@ namespace OpenSim.Region.RegionCombinerModule
newConn.RegionId = scene.RegionInfo.originRegionID;
newConn.X = scene.RegionInfo.RegionLocX;
newConn.Y = scene.RegionInfo.RegionLocY;
- newConn.XEnd = (int)Constants.RegionSize;
- newConn.YEnd = (int)Constants.RegionSize;
+ newConn.XEnd = scene.RegionInfo.RegionSizeX;
+ newConn.YEnd = scene.RegionInfo.RegionSizeX;
lock (m_regions)
{
@@ -415,6 +437,11 @@ namespace OpenSim.Region.RegionCombinerModule
*/
#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
@@ -431,7 +458,7 @@ namespace OpenSim.Region.RegionCombinerModule
//xxx
if (rootConn.PosX >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
{
- connectedYN = DoWorkForOneRegionOverXPlusY(rootConn, newConn, scene);
+ connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
break;
}
@@ -441,9 +468,8 @@ namespace OpenSim.Region.RegionCombinerModule
//xxx
if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY + rootConn.YEnd >= newConn.PosY)
{
- connectedYN = DoWorkForOneRegionOverPlusXPlusY(rootConn, newConn, scene);
+ connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
break;
-
}
}
@@ -453,20 +479,20 @@ namespace OpenSim.Region.RegionCombinerModule
DoWorkForRootRegion(newConn, scene);
}
}
-
- // Set up infinite borders around the entire AABB of the combined ConnectedRegions
- AdjustLargeRegionBounds();
}
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.Y = rootConn.YEnd;
- extents.X = rootConn.XEnd + newConn.XEnd;
+ 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);
@@ -475,9 +501,6 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.RegionInfo.RegionName,
newConn.RegionScene.RegionInfo.RegionName, offset, extents);
- scene.BordersLocked = true;
- rootConn.RegionScene.BordersLocked = true;
-
RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -490,34 +513,10 @@ namespace OpenSim.Region.RegionCombinerModule
// Inform Child region that it needs to forward it's terrain to the root region
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
- // Extend the borders as appropriate
- lock (rootConn.RegionScene.EastBorders)
- rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.NorthBorders)
- rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.SouthBorders)
- rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (scene.WestBorders)
- {
- scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
-
- // Trigger auto teleport to root region
- scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
// 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());
- // Unlock borders
- rootConn.RegionScene.BordersLocked = false;
- scene.BordersLocked = false;
-
// Create a client event forwarder and add this region's events to the root region.
if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -525,6 +524,9 @@ namespace OpenSim.Region.RegionCombinerModule
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;
@@ -536,9 +538,6 @@ namespace OpenSim.Region.RegionCombinerModule
extents.X = rootConn.XEnd;
rootConn.UpdateExtents(extents);
- scene.BordersLocked = true;
- rootConn.RegionScene.BordersLocked = true;
-
RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -553,30 +552,11 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
- lock (rootConn.RegionScene.NorthBorders)
- rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.EastBorders)
- rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.WestBorders)
- rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (scene.SouthBorders)
- {
- scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
- scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
// 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());
- scene.BordersLocked = false;
- rootConn.RegionScene.BordersLocked = false;
-
if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -600,9 +580,6 @@ namespace OpenSim.Region.RegionCombinerModule
extents.Y = rootConn.YEnd;
extents.X = rootConn.XEnd;
- scene.BordersLocked = true;
- rootConn.RegionScene.BordersLocked = true;
-
RegionData ConnectedRegion = new RegionData();
ConnectedRegion.Offset = offset;
ConnectedRegion.RegionId = scene.RegionInfo.originRegionID;
@@ -618,67 +595,10 @@ namespace OpenSim.Region.RegionCombinerModule
rootConn.RegionScene.PhysicsScene.Combine(null, Vector3.Zero, extents);
scene.PhysicsScene.Combine(rootConn.RegionScene.PhysicsScene, offset, Vector3.Zero);
- lock (rootConn.RegionScene.NorthBorders)
- {
- if (rootConn.RegionScene.NorthBorders.Count == 1)// && 2)
- {
- //compound border
- // already locked above
- rootConn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.EastBorders)
- rootConn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.WestBorders)
- rootConn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- }
- }
-
- lock (scene.SouthBorders)
- {
- scene.SouthBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocY - rootConn.RegionScene.RegionInfo.RegionLocY) * (int)Constants.RegionSize); //auto teleport south
- scene.SouthBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.SouthBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
- lock (rootConn.RegionScene.EastBorders)
- {
- if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
- {
- rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.NorthBorders)
- rootConn.RegionScene.NorthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
-
- lock (rootConn.RegionScene.SouthBorders)
- rootConn.RegionScene.SouthBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- }
- }
-
- lock (scene.WestBorders)
- {
- scene.WestBorders[0].BorderLine.Z = (int)((scene.RegionInfo.RegionLocX - rootConn.RegionScene.RegionInfo.RegionLocX) * (int)Constants.RegionSize); //auto teleport West
- scene.WestBorders[0].TriggerRegionX = rootConn.RegionScene.RegionInfo.RegionLocX;
- scene.WestBorders[0].TriggerRegionY = rootConn.RegionScene.RegionInfo.RegionLocY;
- }
-
- /*
- else
- {
- conn.RegionScene.NorthBorders[0].BorderLine.Z += (int)Constants.RegionSize;
- conn.RegionScene.EastBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- conn.RegionScene.WestBorders[0].BorderLine.Y += (int)Constants.RegionSize;
- scene.SouthBorders[0].BorderLine.Z += (int)Constants.RegionSize; //auto teleport south
- }
- */
-
-
// 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());
- scene.BordersLocked = false;
- rootConn.RegionScene.BordersLocked = false;
if (rootConn.ClientEventForwarder != null)
rootConn.ClientEventForwarder.AddSceneToEventForwarding(scene);
@@ -687,6 +607,7 @@ namespace OpenSim.Region.RegionCombinerModule
//scene.PhysicsScene.Combine(conn.RegionScene.PhysicsScene, offset,extents);
}
+ */
private void DoWorkForRootRegion(RegionConnections rootConn, Scene scene)
{
@@ -885,125 +806,6 @@ namespace OpenSim.Region.RegionCombinerModule
// }
// }
- // Create a set of infinite borders around the whole aabb of the combined island.
- private void AdjustLargeRegionBounds()
- {
- lock (m_regions)
- {
- foreach (RegionConnections rconn in m_regions.Values)
- {
- Vector3 offset = Vector3.Zero;
- rconn.RegionScene.BordersLocked = true;
- foreach (RegionData rdata in rconn.ConnectedRegions)
- {
- if (rdata.Offset.X > offset.X) offset.X = rdata.Offset.X;
- if (rdata.Offset.Y > offset.Y) offset.Y = rdata.Offset.Y;
- }
-
- lock (rconn.RegionScene.NorthBorders)
- {
- Border northBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.NorthBorders, out northBorder))
- {
- northBorder = new Border();
- rconn.RegionScene.NorthBorders.Add(northBorder);
- }
-
- northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue,
- offset.Y + (int) Constants.RegionSize); //<---
- northBorder.CrossDirection = Cardinals.N;
- }
-
- lock (rconn.RegionScene.SouthBorders)
- {
- Border southBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.SouthBorders, out southBorder))
- {
- southBorder = new Border();
- rconn.RegionScene.SouthBorders.Add(southBorder);
- }
- southBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
- southBorder.CrossDirection = Cardinals.S;
- }
-
- lock (rconn.RegionScene.EastBorders)
- {
- Border eastBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.EastBorders, out eastBorder))
- {
- eastBorder = new Border();
- rconn.RegionScene.EastBorders.Add(eastBorder);
- }
- eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, offset.X + (int)Constants.RegionSize);
- //<---
- eastBorder.CrossDirection = Cardinals.E;
- }
-
- lock (rconn.RegionScene.WestBorders)
- {
- Border westBorder = null;
- // If we don't already have an infinite border, create one.
- if (!TryGetInfiniteBorder(rconn.RegionScene.WestBorders, out westBorder))
- {
- westBorder = new Border();
- rconn.RegionScene.WestBorders.Add(westBorder);
-
- }
- westBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, 0); //--->
- westBorder.CrossDirection = Cardinals.W;
- }
-
- rconn.RegionScene.BordersLocked = false;
- }
- }
- }
-
- ///
- /// Try and get an Infinite border out of a listT of borders
- ///
- ///
- ///
- ///
- public static bool TryGetInfiniteBorder(List borders, out Border oborder)
- {
- // Warning! Should be locked before getting here!
- foreach (Border b in borders)
- {
- if (b.BorderLine.X == float.MinValue && b.BorderLine.Y == float.MaxValue)
- {
- oborder = b;
- return true;
- }
- }
-
- oborder = null;
- return false;
- }
-
- public RegionData GetRegionFromPosition(Vector3 pPosition)
- {
- pPosition = pPosition/(int) Constants.RegionSize;
- int OffsetX = (int) pPosition.X;
- int OffsetY = (int) pPosition.Y;
-
- lock (m_regions)
- {
- foreach (RegionConnections regConn in m_regions.Values)
- {
- foreach (RegionData reg in regConn.ConnectedRegions)
- {
- if (reg.Offset.X == OffsetX && reg.Offset.Y == OffsetY)
- return reg;
- }
- }
- }
-
- return new RegionData();
- }
-
public void ForwardPermissionRequests(RegionConnections BigRegion, Scene VirtualRegion)
{
if (BigRegion.PermissionModule == null)
diff --git a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs b/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
index fba51d2efa..6bf1c4aea2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
@@ -64,12 +64,12 @@ namespace OpenSim.Region.RegionCombinerModule
///
/// The X meters position of this connection.
///
- public uint PosX { get { return X * Constants.RegionSize; } }
+ public uint PosX { get { return Util.RegionToWorldLoc(X); } }
///
/// The Y meters co-ordinate of this connection.
///
- public uint PosY { get { return Y * Constants.RegionSize; } }
+ public uint PosY { get { return Util.RegionToWorldLoc(Y); } }
///
/// The size of the megaregion in meters.
@@ -91,4 +91,4 @@ namespace OpenSim.Region.RegionCombinerModule
YEnd = (uint)extents.Y;
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 3c8f54fd06..b5ba4a0d62 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2352,7 +2352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
//
// This workaround is to prevent silent failure of this function.
// According to the specification on the SL Wiki, providing a position outside of the
- if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize)
+ if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
{
return 0;
}
@@ -2362,9 +2362,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.ParentGroup.IsAttachment || // return FALSE if attachment
(
pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
- pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
+ pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
- pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
+ pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
)
)
@@ -4655,10 +4655,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
DataserverPlugin.RegisterRequest(m_host.LocalId,
m_item.ItemID, item.AssetID.ToString());
- Vector3 region = new Vector3(
- World.RegionInfo.RegionLocX * Constants.RegionSize,
- World.RegionInfo.RegionLocY * Constants.RegionSize,
- 0);
+ Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
World.AssetService.Get(item.AssetID.ToString(), this,
delegate(string i, object sender, AssetBase a)
@@ -5949,7 +5946,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Vector llGetRegionCorner()
{
m_host.AddScriptLPS(1);
- return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
+ return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
}
///
@@ -6104,7 +6101,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSL_Float mag;
if (dir.x > 0)
{
- mag = (Constants.RegionSize - pos.x) / dir.x;
+ mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
}
else
{
@@ -6115,7 +6112,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
edge.y = pos.y + (dir.y * mag);
- if (edge.y > Constants.RegionSize || edge.y < 0)
+ if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
{
// Y goes out of bounds first
edge.y = dir.y / Math.Abs(dir.y);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index d2a59807da..01d90e7592 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -459,7 +459,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0)
+ if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
OSSLError("osSetTerrainHeight: Coordinate out of bounds");
if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0)))
@@ -489,7 +489,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
private LSL_Float GetTerrainHeight(int x, int y)
{
m_host.AddScriptLPS(1);
- if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0)
+ if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
OSSLError("osGetTerrainHeight: Coordinate out of bounds");
return World.Heightmap[x, y];
@@ -823,7 +823,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
private void TeleportAgent(string agent, int regionX, int regionY,
LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
{
- ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
+ ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY);
m_host.AddScriptLPS(1);
UUID agentId = new UUID();
@@ -3024,7 +3024,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else
{
- return new LSL_Vector((float)Constants.RegionSize, (float)Constants.RegionSize, Constants.RegionHeight);
+ return new LSL_Vector((float)World.RegionInfo.RegionSizeX,
+ (float)World.RegionInfo.RegionSizeY,
+ (float)World.RegionInfo.RegionSizeZ );
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 9cf7b35ad2..86664210ea 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -708,18 +708,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
}
private void Save()
{
+ /* Remove temporarily until we have a handle to the region size
if (Position.x > ((int)Constants.RegionSize - 1))
Position.x = ((int)Constants.RegionSize - 1);
- if (Position.x < 0)
- Position.x = 0;
if (Position.y > ((int)Constants.RegionSize - 1))
Position.y = ((int)Constants.RegionSize - 1);
+ */
+ if (Position.x < 0)
+ Position.x = 0;
if (Position.y < 0)
Position.y = 0;
- if (Position.z > 768)
- Position.z = 768;
if (Position.z < 0)
Position.z = 0;
+ if (Position.z > Constants.RegionHeight)
+ Position.z = Constants.RegionHeight;
prim.OSSL.llSetPos(Position);
}
diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
index 7ee347ca4d..d2fbfa65d1 100644
--- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
+++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
@@ -133,7 +133,7 @@ namespace OpenSim.Server.Handlers.MapImage
if (m_GridService != null)
{
System.Net.IPAddress ipAddr = GetCallerIP(httpRequest);
- GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, x * (int)Constants.RegionSize, y * (int)Constants.RegionSize);
+ GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y));
if (r != null)
{
if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString())
diff --git a/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs
index 8a31579c7f..88d774a4f6 100644
--- a/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs
+++ b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Server.Handlers.MapImage
if (m_GridService != null)
{
System.Net.IPAddress ipAddr = GetCallerIP(httpRequest);
- GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, x * (int)Constants.RegionSize, y * (int)Constants.RegionSize);
+ GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y));
if (r != null)
{
if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString())
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 3cf341630c..312832f08c 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
- Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
+ Vector3d maxPosition = minPosition + new Vector3d(regionInfo.RegionSizeX, regionInfo.RegionSizeY, Constants.RegionHeight);
OSDMap extraData = new OSDMap
{
@@ -174,8 +174,8 @@ namespace OpenSim.Services.Connectors.SimianGrid
if (region != null)
{
List regions = GetRegionRange(scopeID,
- region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + (int)Constants.RegionSize + NEIGHBOR_RADIUS,
- region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + (int)Constants.RegionSize + NEIGHBOR_RADIUS);
+ region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + region.RegionSizeX + NEIGHBOR_RADIUS,
+ region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + region.RegionSizeY + NEIGHBOR_RADIUS);
for (int i = 0; i < regions.Count; i++)
{
@@ -240,7 +240,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
else
{
// m_log.InfoFormat("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at {0},{1}",
- // x / Constants.RegionSize, y / Constants.RegionSize);
+ // Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
return null;
}
}
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
index 96c02d90fc..475983816c 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
@@ -100,6 +100,11 @@ namespace OpenSim.Services.Connectors
return m_database.LoadObjects(regionUUID);
}
+ public void StoreTerrain(TerrainData terrain, UUID regionID)
+ {
+ m_database.StoreTerrain(terrain, regionID);
+ }
+
public void StoreTerrain(double[,] terrain, UUID regionID)
{
m_database.StoreTerrain(terrain, regionID);
@@ -110,6 +115,11 @@ namespace OpenSim.Services.Connectors
return m_database.LoadTerrain(regionID);
}
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ return m_database.LoadTerrain(regionID, pSizeX, pSizeY, pSizeZ);
+ }
+
public void StoreLandObject(ILandObject Parcel)
{
m_database.StoreLandObject(Parcel);
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index 76415ce7c2..eb44dcb217 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -655,7 +655,7 @@ namespace OpenSim.Services.GridService
return;
}
- RegionData region = m_Database.Get(x * (int)Constants.RegionSize, y * (int)Constants.RegionSize, UUID.Zero);
+ RegionData region = m_Database.Get((int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y), UUID.Zero);
if (region == null)
{
MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y);
@@ -673,6 +673,7 @@ namespace OpenSim.Services.GridService
dispList.AddRow("Region Name", r.RegionName);
dispList.AddRow("Region ID", r.RegionID);
dispList.AddRow("Location", string.Format("{0},{1}", r.coordX, r.coordY));
+ dispList.AddRow("Size", string.Format("{0}x{1}", r.sizeX, r.sizeY));
dispList.AddRow("URI", r.Data["serverURI"]);
dispList.AddRow("Owner ID", r.Data["owner_uuid"]);
dispList.AddRow("Flags", flags);
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 402429597b..0448b54b51 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -183,8 +183,8 @@ namespace OpenSim.Services.GridService
public GridRegion LinkRegion(UUID scopeID, string regionDescriptor)
{
string reason = string.Empty;
- int xloc = random.Next(0, Int16.MaxValue) * (int)Constants.RegionSize;
- return TryLinkRegionToCoords(scopeID, regionDescriptor, xloc, 0, out reason);
+ uint xloc = Util.RegionToWorldLoc((uint)random.Next(0, Int16.MaxValue));
+ return TryLinkRegionToCoords(scopeID, regionDescriptor, (int)xloc, 0, out reason);
}
private static Random random = new Random();
@@ -260,7 +260,7 @@ namespace OpenSim.Services.GridService
{
m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0} {1}, in {2}-{3}",
((serverURI == null) ? (externalHostName + ":" + externalPort) : serverURI),
- remoteRegionName, xloc / Constants.RegionSize, yloc / Constants.RegionSize);
+ remoteRegionName, Util.WorldToRegionLoc((uint)xloc), Util.WorldToRegionLoc((uint)yloc));
reason = string.Empty;
Uri uri = null;
@@ -311,7 +311,7 @@ namespace OpenSim.Services.GridService
if (region != null)
{
m_log.WarnFormat("[HYPERGRID LINKER]: Coordinates {0}-{1} are already occupied by region {2} with uuid {3}",
- regInfo.RegionLocX / Constants.RegionSize, regInfo.RegionLocY / Constants.RegionSize,
+ Util.WorldToRegionLoc((uint)regInfo.RegionLocX), Util.WorldToRegionLoc((uint)regInfo.RegionLocY),
region.RegionName, region.RegionID);
reason = "Coordinates are already in use";
return false;
@@ -347,7 +347,7 @@ namespace OpenSim.Services.GridService
if (region != null)
{
m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates {0} {1}",
- region.RegionLocX / Constants.RegionSize, region.RegionLocY / Constants.RegionSize);
+ Util.WorldToRegionLoc((uint)regInfo.RegionLocX), Util.WorldToRegionLoc((uint)regInfo.RegionLocY));
regInfo = region;
return true;
}
@@ -424,10 +424,10 @@ namespace OpenSim.Services.GridService
// {
// uint ux = 0, uy = 0;
// Utils.LongToUInts(realHandle, out ux, out uy);
-// x = ux / Constants.RegionSize;
-// y = uy / Constants.RegionSize;
+// x = Util.WorldToRegionLoc(ux);
+// y = Util.WorldToRegionLoc(uy);
//
-// const uint limit = (4096 - 1) * Constants.RegionSize;
+// const uint limit = Util.RegionToWorldLoc(4096 - 1);
// uint xmin = ux - limit;
// uint xmax = ux + limit;
// uint ymin = uy - limit;
@@ -503,8 +503,9 @@ namespace OpenSim.Services.GridService
foreach (RegionData r in regions)
{
MainConsole.Instance.Output(String.Format("{0}\n{2,-32} {1}\n",
- r.RegionName, r.RegionID, String.Format("{0},{1} ({2},{3})", r.posX, r.posY,
- r.posX / Constants.RegionSize, r.posY / Constants.RegionSize)));
+ r.RegionName, r.RegionID,
+ String.Format("{0},{1} ({2},{3})", r.posX, r.posY,
+ Util.WorldToRegionLoc((uint)r.posX), Util.WorldToRegionLoc((uint)r.posY))) );
}
return;
}
@@ -529,8 +530,8 @@ namespace OpenSim.Services.GridService
int xloc, yloc;
string serverURI;
string remoteName = null;
- xloc = Convert.ToInt32(cmdparams[0]) * (int)Constants.RegionSize;
- yloc = Convert.ToInt32(cmdparams[1]) * (int)Constants.RegionSize;
+ xloc = (int)Util.RegionToWorldLoc((uint)Convert.ToInt32(cmdparams[0]));
+ yloc = (int)Util.RegionToWorldLoc((uint)Convert.ToInt32(cmdparams[1]));
serverURI = cmdparams[2];
if (cmdparams.Length > 3)
remoteName = string.Join(" ", cmdparams, 3, cmdparams.Length - 3);
@@ -601,13 +602,13 @@ namespace OpenSim.Services.GridService
{
// old format
GridRegion regInfo;
- int xloc, yloc;
+ uint xloc, yloc;
uint externalPort;
string externalHostName;
try
{
- xloc = Convert.ToInt32(cmdparams[0]);
- yloc = Convert.ToInt32(cmdparams[1]);
+ xloc = (uint)Convert.ToInt32(cmdparams[0]);
+ yloc = (uint)Convert.ToInt32(cmdparams[1]);
externalPort = Convert.ToUInt32(cmdparams[3]);
externalHostName = cmdparams[2];
//internalPort = Convert.ToUInt32(cmdparams[4]);
@@ -621,10 +622,11 @@ namespace OpenSim.Services.GridService
}
// Convert cell coordinates given by the user to meters
- xloc = xloc * (int)Constants.RegionSize;
- yloc = yloc * (int)Constants.RegionSize;
+ xloc = Util.RegionToWorldLoc(xloc);
+ yloc = Util.RegionToWorldLoc(yloc);
string reason = string.Empty;
- if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
+ if (TryCreateLink(UUID.Zero, (int)xloc, (int)yloc,
+ string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
{
// What is this? The GridRegion instance will be discarded anyway,
// which effectively ignores any local name given with the command.
@@ -704,13 +706,13 @@ namespace OpenSim.Services.GridService
private void ReadLinkFromConfig(IConfig config)
{
GridRegion regInfo;
- int xloc, yloc;
+ uint xloc, yloc;
uint externalPort;
string externalHostName;
uint realXLoc, realYLoc;
- xloc = Convert.ToInt32(config.GetString("xloc", "0"));
- yloc = Convert.ToInt32(config.GetString("yloc", "0"));
+ xloc = (uint)Convert.ToInt32(config.GetString("xloc", "0"));
+ yloc = (uint)Convert.ToInt32(config.GetString("yloc", "0"));
externalPort = Convert.ToUInt32(config.GetString("externalPort", "0"));
externalHostName = config.GetString("externalHostName", "");
realXLoc = Convert.ToUInt32(config.GetString("real-xloc", "0"));
@@ -718,18 +720,19 @@ namespace OpenSim.Services.GridService
if (m_enableAutoMapping)
{
- xloc = (int)((xloc % 100) + m_autoMappingX);
- yloc = (int)((yloc % 100) + m_autoMappingY);
+ xloc = (uint)((xloc % 100) + m_autoMappingX);
+ yloc = (uint)((yloc % 100) + m_autoMappingY);
}
if (((realXLoc == 0) && (realYLoc == 0)) ||
(((realXLoc - xloc < 3896) || (xloc - realXLoc < 3896)) &&
((realYLoc - yloc < 3896) || (yloc - realYLoc < 3896))))
{
- xloc = xloc * (int)Constants.RegionSize;
- yloc = yloc * (int)Constants.RegionSize;
+ xloc = Util.RegionToWorldLoc(xloc);
+ yloc = Util.RegionToWorldLoc(yloc);
string reason = string.Empty;
- if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
+ if (TryCreateLink(UUID.Zero, (int)xloc, (int)yloc,
+ string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
{
regInfo.RegionName = config.GetString("localName", "");
}
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index 19ea0fed1f..1119e48a63 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -179,14 +179,14 @@ namespace OpenSim.Services.Interfaces
protected IPEndPoint m_internalEndPoint;
///
- /// The co-ordinate of this region.
+ /// The co-ordinate of this region in region units.
///
- public int RegionCoordX { get { return RegionLocX / (int)Constants.RegionSize; } }
+ public int RegionCoordX { get { return (int)Util.WorldToRegionLoc((uint)RegionLocX); } }
///
- /// The co-ordinate of this region
+ /// The co-ordinate of this region in region units
///
- public int RegionCoordY { get { return RegionLocY / (int)Constants.RegionSize; } }
+ public int RegionCoordY { get { return (int)Util.WorldToRegionLoc((uint)RegionLocY); } }
///
/// The location of this region in meters.
@@ -265,8 +265,8 @@ namespace OpenSim.Services.Interfaces
public GridRegion(uint xcell, uint ycell)
{
- m_regionLocX = (int)(xcell * Constants.RegionSize);
- m_regionLocY = (int)(ycell * Constants.RegionSize);
+ m_regionLocX = (int)Util.RegionToWorldLoc(xcell);
+ m_regionLocY = (int)Util.RegionToWorldLoc(ycell);
RegionSizeX = (int)Constants.RegionSize;
RegionSizeY = (int)Constants.RegionSize;
}
@@ -274,8 +274,8 @@ namespace OpenSim.Services.Interfaces
public GridRegion(RegionInfo ConvertFrom)
{
m_regionName = ConvertFrom.RegionName;
- m_regionLocX = (int)(ConvertFrom.RegionLocX * Constants.RegionSize);
- m_regionLocY = (int)(ConvertFrom.RegionLocY * Constants.RegionSize);
+ m_regionLocX = (int)(ConvertFrom.WorldLocX);
+ m_regionLocY = (int)(ConvertFrom.WorldLocY);
RegionSizeX = (int)ConvertFrom.RegionSizeX;
RegionSizeY = (int)ConvertFrom.RegionSizeY;
m_internalEndPoint = ConvertFrom.InternalEndPoint;
diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
index f641955969..da351b9add 100644
--- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
@@ -368,7 +368,8 @@ namespace OpenSim.Services.LLLoginService
private void FillOutHomeData(GridUserInfo pinfo, GridRegion home)
{
- int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize;
+ int x = (int)Util.RegionToWorldLoc(1000);
+ int y = (int)Util.RegionToWorldLoc(1000);
if (home != null)
{
x = home.RegionLocX;
@@ -443,10 +444,23 @@ namespace OpenSim.Services.LLLoginService
ErrorReason = "key";
welcomeMessage = "Welcome to OpenSim!";
seedCapability = String.Empty;
- home = "{'region_handle':[r" + (1000*Constants.RegionSize).ToString() + ",r" + (1000*Constants.RegionSize).ToString() + "], 'position':[r" +
- userProfile.homepos.X.ToString() + ",r" + userProfile.homepos.Y.ToString() + ",r" +
- userProfile.homepos.Z.ToString() + "], 'look_at':[r" + userProfile.homelookat.X.ToString() + ",r" +
- userProfile.homelookat.Y.ToString() + ",r" + userProfile.homelookat.Z.ToString() + "]}";
+ home = "{'region_handle':["
+ + "r" + Util.RegionToWorldLoc(1000).ToString()
+ + ","
+ + "r" + Util.RegionToWorldLoc(1000).ToString()
+ + "], 'position':["
+ + "r" + userProfile.homepos.X.ToString()
+ + ","
+ + "r" + userProfile.homepos.Y.ToString()
+ + ","
+ + "r" + userProfile.homepos.Z.ToString()
+ + "], 'look_at':["
+ + "r" + userProfile.homelookat.X.ToString()
+ + ","
+ + "r" + userProfile.homelookat.Y.ToString()
+ + ","
+ + "r" + userProfile.homelookat.Z.ToString()
+ + "]}";
lookAt = "[r0.99949799999999999756,r0.03166859999999999814,r0]";
RegionX = (uint) 255232;
RegionY = (uint) 254976;
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 1c1c9b0a98..c8331312d1 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -695,7 +695,7 @@ namespace OpenSim.Services.LLLoginService
private GridRegion FindAlternativeRegion(UUID scopeID)
{
List hyperlinks = null;
- List regions = m_GridService.GetFallbackRegions(scopeID, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize);
+ List regions = m_GridService.GetFallbackRegions(scopeID, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000));
if (regions != null && regions.Count > 0)
{
hyperlinks = m_GridService.GetHyperlinks(scopeID);
diff --git a/OpenSim/Tests/Clients/Grid/GridClient.cs b/OpenSim/Tests/Clients/Grid/GridClient.cs
index 8e3337319b..fed7a16922 100644
--- a/OpenSim/Tests/Clients/Grid/GridClient.cs
+++ b/OpenSim/Tests/Clients/Grid/GridClient.cs
@@ -150,16 +150,16 @@ namespace OpenSim.Tests.Clients.GridClient
Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 2 regions)");
regions = m_Connector.GetRegionRange(UUID.Zero,
- 900 * (int)Constants.RegionSize, 1002 * (int) Constants.RegionSize,
- 900 * (int)Constants.RegionSize, 1002 * (int) Constants.RegionSize);
+ (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002),
+ (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) );
if (regions == null)
Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
else
Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions");
Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 0 regions)");
regions = m_Connector.GetRegionRange(UUID.Zero,
- 900 * (int)Constants.RegionSize, 950 * (int)Constants.RegionSize,
- 900 * (int)Constants.RegionSize, 950 * (int)Constants.RegionSize);
+ (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950),
+ (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) );
if (regions == null)
Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
else
diff --git a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs b/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
index 52a17e7a5f..84de47f5df 100644
--- a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
@@ -69,9 +69,7 @@ namespace OpenSim.Tests.Common
tc.OnTestClientInformClientOfNeighbour += (neighbourHandle, neighbourExternalEndPoint) =>
{
uint x, y;
- Utils.LongToUInts(neighbourHandle, out x, out y);
- x /= Constants.RegionSize;
- y /= Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(neighbourHandle, out x, out y);
m_log.DebugFormat(
"[TEST CLIENT]: Processing inform client of neighbour located at {0},{1} at {2}",
@@ -104,9 +102,7 @@ namespace OpenSim.Tests.Common
+= (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) =>
{
uint x, y;
- Utils.LongToUInts(regionHandle, out x, out y);
- x /= Constants.RegionSize;
- y /= Constants.RegionSize;
+ Util.RegionHandleToRegionLoc(regionHandle, out x, out y);
m_log.DebugFormat(
"[TEST CLIENT]: Processing send region teleport for destination at {0},{1} at {2}",
@@ -125,4 +121,4 @@ namespace OpenSim.Tests.Common
};
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
index 5c1ec0bebd..3ab90207a5 100644
--- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
@@ -69,11 +69,21 @@ namespace OpenSim.Data.Null
m_store.StoreTerrain(terrain, regionID);
}
+ public void StoreTerrain(TerrainData terrain, UUID regionID)
+ {
+ m_store.StoreTerrain(terrain, regionID);
+ }
+
public double[,] LoadTerrain(UUID regionID)
{
return m_store.LoadTerrain(regionID);
}
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ return m_store.LoadTerrain(regionID, pSizeX, pSizeY, pSizeZ);
+ }
+
public void StoreLandObject(ILandObject Parcel)
{
m_store.StoreLandObject(Parcel);
@@ -159,7 +169,7 @@ namespace OpenSim.Data.Null
protected Dictionary m_sceneObjectParts = new Dictionary();
protected Dictionary> m_primItems
= new Dictionary>();
- protected Dictionary m_terrains = new Dictionary();
+ protected Dictionary m_terrains = new Dictionary();
protected Dictionary m_landData = new Dictionary();
public void Initialise(string dbfile)
@@ -304,15 +314,28 @@ namespace OpenSim.Data.Null
return new List(objects.Values);
}
- public void StoreTerrain(double[,] ter, UUID regionID)
+ public void StoreTerrain(TerrainData ter, UUID regionID)
{
m_terrains[regionID] = ter;
}
+ public void StoreTerrain(double[,] ter, UUID regionID)
+ {
+ m_terrains[regionID] = new HeightmapTerrainData(ter);
+ }
+
+ public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ)
+ {
+ if (m_terrains.ContainsKey(regionID))
+ return m_terrains[regionID];
+ else
+ return null;
+ }
+
public double[,] LoadTerrain(UUID regionID)
{
if (m_terrains.ContainsKey(regionID))
- return m_terrains[regionID];
+ return m_terrains[regionID].GetDoubles();
else
return null;
}