From 9f18e3ba80a6469b7ff03c7cca595a0a3b999592 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sun, 22 Mar 2015 21:53:02 -0700
Subject: Varregion: first cut at removing Border class checks for region
crossings. Added Scene.PositionIsInCurrentRegion(pos) to sense when new
position needs some crossing work. Many changes made to EntityTransferModule
to accomodate new crossing sense logic.
---
OpenSim/Framework/RegionInfo.cs | 31 +-
.../EntityTransfer/EntityTransferModule.cs | 840 ++++++++++-----------
.../Framework/Interfaces/IRegionCombinerModule.cs | 5 +
OpenSim/Region/Framework/Scenes/Scene.cs | 325 +-------
.../Region/Framework/Scenes/SceneObjectGroup.cs | 10 +-
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 5 +-
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 60 +-
.../World/SceneCommands/SceneCommandsModule.cs | 33 +-
.../RegionCombinerModule/RegionCombinerModule.cs | 320 ++------
9 files changed, 526 insertions(+), 1103 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index ae2ff63..90188d2 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));
}
}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index b32a169..0f6c507 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -121,8 +121,53 @@ 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)
+ {
+ if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
+ {
+ m_idCache = new ExpiringCache();
+ m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45));
+ }
+ m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
+ }
+ // 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 +382,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 +464,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 +483,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 +527,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 +580,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.Access = (byte)SimAccess.Down; // == not there
List blocks = new List();
blocks.Add(block);
@@ -550,6 +593,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 +718,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 +742,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 +1342,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 +1369,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
@@ -1390,214 +1447,80 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Crossings
- public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason)
- {
- reason = String.Empty;
- version = String.Empty;
-
- UUID agentID = agent.UUID;
- ulong destinyHandle = destiny.RegionHandle;
-
- ExpiringCache r;
- DateTime banUntil;
- if (m_bannedRegions.TryGetValue(agentID, out r))
- {
- if (r.TryGetValue(destinyHandle, out banUntil))
- {
- if (DateTime.Now < banUntil)
- {
- reason = "Cannot connect to region";
- return false;
- }
- r.Remove(destinyHandle);
- }
- }
- else
- {
- r = null;
- }
-
- 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));
- }
- return false;
- }
- return true;
- }
-
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
{
string r = String.Empty;
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;
-
-/*
- 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);
+ // 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));
- // 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))
- {
- Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
- }
- else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
- {
- neighboury--;
- newpos.Y += Constants.RegionSize;
- }
-
- 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;
+ // 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 (scene.TestBorderCross(pos + southCross, Cardinals.S))
+ if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
{
- neighboury--;
- newpos.Y += Constants.RegionSize;
+ failureReason = "Cannot region cross into banned parcel";
+ neighbourRegion = null;
}
- else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
+ else
{
- Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
- neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize);
- newpos.Y -= Constants.RegionSize;
+ // If not banned, make sure this agent is not in the list.
+ m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
}
- }
- 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))
+ // 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))
{
- 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 +1555,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 +1602,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 +1612,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 +1665,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 +1813,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 +1975,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 +2132,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 +2406,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++)
- {
- extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
- }
- for (int i = 0; i < northBorders.Length; i++)
+
+ if (m_regionCombinerModule != null)
{
- 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 +2429,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;
-
- endX += dd;
- endY += dd;
+ uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2;
+ uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2;
- if (startX < 0) startX = 0;
- if (startY < 0) startY = 0;
+ neighbours
+ = avatar.Scene.GridService.GetRegionRange(
+ m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
- 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);
+ (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
+ (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
+ }
- neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
+ // 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;
- }
+ return neighbours;
}
/* not in use
private List NewNeighbours(List currentNeighbours, List previousNeighbours)
@@ -2509,8 +2591,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 +2606,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (scene == null)
return;
+ // Remember the old group position in case the region lookup fails so position can be restored.
+ Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
- 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);
+ // Compute the absolute position of the object.
+ double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X;
+ double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y;
- 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));
+ // Ask the grid service for the region that contains the passed address
+ GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
+ objectWorldLocX, objectWorldLocY);
- newRegionHandle
- = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
- (uint)(thisy * Constants.RegionSize));
- // x - 1
- }
- }
- else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
+ Vector3 pos = Vector3.Zero;
+ if (destination != null)
{
- 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
- }
+ // 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);
}
- 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))
+ if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
{
+ m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID);
- pos.Y = ((pos.Y - Constants.RegionSize));
- newRegionHandle
- = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize));
- // y + 1
- }
+ // 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);
- // Offset the positions for the new region across the border
- Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
+ grp.AbsolutePosition = oldGroupPosition;
+ grp.Velocity = Vector3.Zero;
+ if (grp.RootPart.PhysActor != null)
+ grp.RootPart.PhysActor.CrossingFailure();
- // 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);
+ if (grp.RootPart.KeyframeMotion != null)
+ grp.RootPart.KeyframeMotion.CrossingFailure();
- if (destination != null)
- {
- if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
- return; // we did it
+ grp.ScheduleGroupForFullUpdate();
}
-
- // 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);
-
- 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();
-
- grp.ScheduleGroupForFullUpdate();
}
-
-
///
/// Move the given scene object into a new region
///
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
index e03ac5a..c6f531e 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/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index eb34f55..03270d7 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -160,11 +160,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
@@ -364,7 +359,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 +440,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 +1057,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);
@@ -2611,185 +2571,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)
- {
- 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;
+ 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)
+ {
+ // 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 +3926,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 +4644,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/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 89c7a1a..a99e469 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -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 91293c4..8979659 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 cd9dcf5..2965903 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1170,18 +1170,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)
@@ -3867,32 +3855,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 (!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;
-
- 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;
- }
+
+ if (Scene.PositionIsInCurrentRegion(pos2))
+ return;
+
+ 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;
+
+ 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;
}
}
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 29b39e0..6cbccc0 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/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 7127c73..341c8f8 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)
--
cgit v1.1
From d74d74c9102e1be159c9683c8982384f68e5fb6b Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Fri, 27 Mar 2015 06:47:55 -0700
Subject: varregion: restore checkAgentAccessToRegion routine in
EntityTransferModule.
---
.../EntityTransfer/EntityTransferModule.cs | 33 ++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 0f6c507..809027f 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -151,12 +151,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// 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(45));
+ m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime));
}
- m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
+ 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)
@@ -1447,6 +1451,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Crossings
+ public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason)
+ {
+ reason = String.Empty;
+ version = String.Empty;
+
+ UUID agentID = agent.UUID;
+ ulong destinyHandle = destiny.RegionHandle;
+
+ if (m_bannedRegionCache.IfBanned(destinyHandle, agentID))
+ {
+ reason = "Cannot connect to region";
+ return false;
+ }
+
+ Scene ascene = agent.Scene;
+
+ if (!ascene.SimulationService.QueryAccess(destiny, agentID, position, out version, out reason))
+ {
+ m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
+ return false;
+ }
+
+ return true;
+ }
+
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
{
string r = String.Empty;
--
cgit v1.1
From bedafb8fae9898ef0c5fc6470236ee7244e616a9 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Fri, 27 Mar 2015 19:32:50 -0700
Subject: varregion: refactor use of 'double heightmap[,]' into references to
new class TerrainData and push the implementation from Scene into the
database readers and writers.
---
OpenSim/Data/MSSQL/MSSQLSimulationData.cs | 83 ++--
OpenSim/Data/MySQL/MySQLSimulationData.cs | 66 +--
OpenSim/Data/Null/NullSimulationData.cs | 22 +-
OpenSim/Data/PGSQL/PGSQLSimulationData.cs | 72 +--
OpenSim/Data/SQLite/SQLiteSimulationData.cs | 54 ++-
OpenSim/Framework/TerrainData.cs | 464 ++++++++++++++++++++
.../Terrain/FileLoaders/GenericSystemDrawing.cs | 2 +-
.../CoreModules/World/Terrain/TerrainModule.cs | 488 ++++++++++++++++-----
.../Framework/Interfaces/ISimulationDataService.cs | 9 +
.../Framework/Interfaces/ISimulationDataStore.cs | 10 +
.../Region/Framework/Interfaces/ITerrainChannel.cs | 19 +-
OpenSim/Region/Framework/Scenes/Scene.cs | 4 +-
OpenSim/Region/Framework/Scenes/TerrainChannel.cs | 352 ++++++++++-----
.../Connectors/Simulation/SimulationDataService.cs | 10 +
OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs | 29 +-
15 files changed, 1359 insertions(+), 325 deletions(-)
create mode 100644 OpenSim/Framework/TerrainData.cs
(limited to 'OpenSim')
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index 0d09be6..145b9c0 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;
+ else
+ {
+ _Log.Info("[REGION DB]: No terrain found for region");
+ return null;
+ }
+ _Log.Info("[REGION DB]: Loaded terrain");
}
- _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 cc844ae..f910e44 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 15824a9..339e7f4 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -132,18 +132,36 @@ 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))
+ {
return m_terrains[regionID];
}
return null;
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
index 3243635..cd02e05 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 4d6a80a..d28c227 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/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
new file mode 100644
index 0000000..6b1be4e
--- /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/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d78ade5..d5c77ec 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/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 4d738a5..9a88804 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}",
@@ -634,7 +767,44 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
///
+ /// 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);
- }
+ ScenePresence presence = scene.GetScenePresence(client);
+ if (presence != null)
+ {
+ presence.ControllingClient.OnModifyTerrain -= client_OnModifyTerrain;
+ presence.ControllingClient.OnBakeTerrain -= client_OnBakeTerrain;
+ presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
+ presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
+ }
+ lock (m_perClientPatchUpdates)
+ m_perClientPatchUpdates.Remove(client);
+ }
+
///
- /// 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
+ /// 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 void CheckForTerrainUpdates(bool respectEstateSettings)
+ private bool EnforceEstateLimits()
{
- bool shouldTaint = false;
- float[] serialised = m_channel.GetFloatsSerialised();
- int x;
- for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
+ TerrainData terrData = m_channel.GetTerrainData();
+
+ bool wasLimited = false;
+ for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
{
- int y;
- for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize)
+ for (int y = 0; y < terrData.SizeY; 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();
- }
-
- SendToClients(serialised, x, y);
- shouldTaint = true;
+ 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)
+ {
+ 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
{
- m_scene.ForEachClient(
- delegate(IClientAPI controller)
- { controller.SendLayerData(
- x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
+ 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/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 3e97a7a..13358cb 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 17bd48b..e09f775 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 e467701..f660b8d 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.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 03270d7..f5458c1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1935,7 +1935,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
@@ -1946,7 +1946,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);
}
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index b6e0a97..3d563a6 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -25,14 +25,21 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-using OpenSim.Framework;
-using OpenSim.Region.Framework.Interfaces;
using System;
+using System.IO;
using System.Text;
+using System.Reflection;
using System.Xml;
-using System.IO;
using System.Xml.Serialization;
+using OpenSim.Data;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+
+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);
- public TerrainChannel(bool createMap)
- {
- if (createMap)
- {
- map = new double[Constants.RegionSize,Constants.RegionSize];
- taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16];
- }
+ 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(int w, int h)
+ public TerrainChannel(TerrainData pTerrData)
{
- map = new double[w,h];
- taint = new bool[w / 16,h / 16];
+ m_terrainData = pTerrData;
}
#region ITerrainChannel Members
- public int Width
+ // ITerrainChannel.MakeCopy()
+ public ITerrainChannel MakeCopy()
{
- get { return map.GetLength(0); }
+ return this.Copy();
}
- public int Height
+ // ITerrainChannel.GetTerrainData()
+ public TerrainData GetTerrainData()
{
- get { return map.GetLength(1); }
+ return m_terrainData;
}
- public ITerrainChannel MakeCopy()
+ // 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()
{
- TerrainChannel copy = new TerrainChannel(false);
- copy.map = (double[,]) map.Clone();
-
- return copy;
+ return m_terrainData.GetFloatsSerialized();
}
- public float[] GetFloatsSerialised()
+ // ITerrainChannel.GetDoubles()
+ public double[,] GetDoubles()
{
- // 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];
+ 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;
}
}
- public bool Tainted(int x, int y)
+ // ITerrainChannel.GetHieghtAtXYZ(x, y, z)
+ public float GetHeightAtXYZ(float x, float y, float z)
{
- if (taint[x / 16, y / 16])
- {
- taint[x / 16, y / 16] = false;
- return true;
- }
- return false;
+ if (x < 0 || x >= Width || y < 0 || y >= Height)
+ return 0;
+ return m_terrainData[(int)x, (int)y];
}
- #endregion
-
- public TerrainChannel Copy()
+ // ITerrainChannel.Tainted()
+ public bool Tainted(int x, int y)
{
- 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();
}
+ // ITerrainChannel.Merge
+ public void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement)
+ {
+ 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)
{
- reader.ReadStartElement("TerrainMap");
- FromXml(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/Services/Connectors/Simulation/SimulationDataService.cs b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
index 96c02d9..4759838 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/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
index 5c1ec0b..3ab9020 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,12 +314,17 @@ 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 double[,] LoadTerrain(UUID regionID)
+ 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];
@@ -317,6 +332,14 @@ namespace OpenSim.Data.Null
return null;
}
+ public double[,] LoadTerrain(UUID regionID)
+ {
+ if (m_terrains.ContainsKey(regionID))
+ return m_terrains[regionID].GetDoubles();
+ else
+ return null;
+ }
+
public void RemoveLandObject(UUID globalID)
{
if (m_landData.ContainsKey(globalID))
--
cgit v1.1
From 08c72a8dc1e54114559521a6c2952905ecf6f105 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sat, 28 Mar 2015 07:50:04 -0700
Subject: varregion: remove use of Constants.RegionSize is various places. More
use of the Util routines for conversion of region handles into addresses.
---
.../ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs | 6 +++---
OpenSim/Data/IRegionData.cs | 8 ++++----
OpenSim/Framework/RegionInfo.cs | 1 +
OpenSim/Framework/UserProfileData.cs | 12 ++++++++----
.../Linden/Caps/EventQueue/EventQueueGetModule.cs | 9 +++++----
5 files changed, 21 insertions(+), 15 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 2120116..cb96a55 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -1155,7 +1155,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);
@@ -1385,7 +1385,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 {
@@ -3116,7 +3116,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 463c621..ca9b327 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/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 90188d2..019fffc 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -825,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/UserProfileData.cs b/OpenSim/Framework/UserProfileData.cs
index 9bac739..f7069a5 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 ca6c3ca..51535a6 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);
--
cgit v1.1
From c5a7bf6601dfde518a008d45b4e4a8dc8de698bf Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sat, 28 Mar 2015 08:30:52 -0700
Subject: varregion: add varregion and TerrainData use in LLClientView. Add
sending multiple parcel patches and sending patches by avatar view distance.
---
OpenSim/Framework/MapBlockData.cs | 18 +
.../Region/ClientStack/Linden/UDP/LLClientView.cs | 273 +++---
.../Region/Framework/Scenes/TerrainCompressor.cs | 948 +++++++++++++++++++++
3 files changed, 1130 insertions(+), 109 deletions(-)
create mode 100644 OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
(limited to 'OpenSim')
diff --git a/OpenSim/Framework/MapBlockData.cs b/OpenSim/Framework/MapBlockData.cs
index 2298ac5..4bee499 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/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 849fec3..4c0fba5 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
///
@@ -690,12 +691,36 @@ 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;
}
}
@@ -1174,11 +1199,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!
@@ -1191,15 +1219,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);
}
}
}
@@ -1209,77 +1238,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;
+ if (px >= 0)
+ {
+ SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
+ }
+ else
+ {
+ 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];
+ }
- float[] heightmap = (map.Length == 65536) ?
- map :
- LLHeightFieldMoronize(map);
+ // DebugSendingPatches("SendLayerData", xPatches, yPatches);
- try
- {
- Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
- OutPacket(layerpack, ThrottleOutPacketType.Land);
+ SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData());
}
- catch
+ }
+
+ private void DebugSendingPatches(string pWho, int[] pX, int[] pY)
+ {
+ if (m_log.IsDebugEnabled)
{
- for (int px = x ; px < x + 4 ; px++)
- SendLayerData(px, y, map);
+ 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.
+ /* 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)
+ {
+ 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);
- // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
- if (m_justEditedTerrain)
- {
- layerpack.Header.Reliable = false;
- OutPacket(layerpack,
- ThrottleOutPacketType.Unknown );
- }
- else
- {
- layerpack.Header.Reliable = true;
- OutPacket(layerpack,
- ThrottleOutPacketType.Task);
+ SendTheLayerPacket(layerpack);
}
}
catch (Exception e)
@@ -1288,36 +1335,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);
}
-
}
///
@@ -1346,21 +1391,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);
}
@@ -1384,7 +1430,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);
}
@@ -1489,10 +1541,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);
}
@@ -1657,15 +1708,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];
@@ -9087,6 +9129,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/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
new file mode 100644
index 0000000..fc8f8cd
--- /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
+ }
+}
--
cgit v1.1
From 07dead7dcb8b0f2a27a50748e4a460d9669903fc Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sun, 29 Mar 2015 14:25:12 -0700
Subject: varregion: any conversions of use of Constants.RegionSize converted
into Util.cs routines to convert region coords to and from world coords or
handles.
---
.../Region/CoreModules/Avatar/Chat/ChatModule.cs | 6 +--
.../Avatar/UserProfiles/UserProfileModule.cs | 6 +--
.../Framework/Caps/CapabilitiesModule.cs | 4 +-
.../EntityTransfer/EntityTransferModule.cs | 4 +-
.../Scripting/EMailModules/EmailModule.cs | 4 +-
.../Grid/LocalGridServiceConnector.cs | 4 +-
.../ServiceConnectorsOut/Grid/RegionCache.cs | 9 +++-
.../Grid/Tests/GridConnectorsTests.cs | 4 +-
.../Neighbour/LocalNeighbourServiceConnector.cs | 4 +-
.../World/Archiver/ArchiveWriteRequest.cs | 2 +-
.../World/Objects/BuySell/BuySellModule.cs | 11 ++---
.../World/Permissions/PermissionsModule.cs | 8 ++--
.../Terrain/Effects/DefaultTerrainGenerator.cs | 4 +-
.../World/Terrain/FileLoaders/Terragen.cs | 35 +++++++-------
.../World/Terrain/FloodBrushes/NoiseArea.cs | 4 +-
.../World/Terrain/PaintBrushes/NoiseSphere.cs | 2 +-
.../CoreModules/World/Terrain/Tests/TerrainTest.cs | 32 +++++++------
OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 11 ++---
OpenSim/Region/Framework/Scenes/Scene.cs | 33 +++++++++++--
.../Framework/Scenes/SceneCommunicationService.cs | 9 ++--
.../Region/Framework/Scenes/SceneObjectGroup.cs | 2 +-
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 25 ++++------
.../Server/IRCClientView.cs | 2 +-
.../OptionalModules/Avatar/Chat/IRCConnector.cs | 2 +
.../OptionalModules/Avatar/Chat/RegionState.cs | 2 +
.../PrimLimitsModule/PrimLimitsModule.cs | 4 +-
.../RegionReadyModule/RegionReadyModule.cs | 5 +-
.../World/TreePopulator/TreePopulatorModule.cs | 4 +-
.../BasicPhysicsPlugin/BasicPhysicsScene.cs | 17 +++++--
.../Region/Physics/Manager/PhysicsPluginManager.cs | 14 +++++-
OpenSim/Region/Physics/Manager/PhysicsScene.cs | 9 ++++
.../RegionCombinerModule/RegionConnections.cs | 6 +--
.../Shared/Api/Implementation/LSL_Api.cs | 17 +++----
.../Shared/Api/Implementation/OSSL_Api.cs | 10 ++--
.../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 10 ++--
.../Server/Handlers/Map/MapAddServerConnector.cs | 2 +-
.../Handlers/Map/MapRemoveServerConnector.cs | 2 +-
.../SimianGrid/SimianGridServiceConnector.cs | 8 ++--
OpenSim/Services/GridService/GridService.cs | 3 +-
OpenSim/Services/GridService/HypergridLinker.cs | 55 ++++++++++++----------
OpenSim/Services/Interfaces/IGridService.cs | 16 +++----
OpenSim/Services/LLLoginService/LLLoginResponse.cs | 24 ++++++++--
OpenSim/Services/LLLoginService/LLLoginService.cs | 2 +-
OpenSim/Tests/Clients/Grid/GridClient.cs | 8 ++--
.../Tests/Common/Helpers/EntityTransferHelpers.cs | 10 ++--
45 files changed, 258 insertions(+), 197 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index dcfc630..9d70063 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 db8405b..7177d9b 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 6e0fd03..f615c6b 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 809027f..c81e5aa 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -587,8 +587,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
MapBlockData block = new MapBlockData();
- block.X = (ushort)(regX / Constants.RegionSize);
- block.Y = (ushort)(regY / Constants.RegionSize);
+ block.X = (ushort)(regX);
+ block.Y = (ushort)(regY);
block.Access = (byte)SimAccess.Down; // == not there
List blocks = new List();
diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
index d943b20..4e7ad75 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 31ef79b..8ccad39 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 9172536..ae76288 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 4338133..6a49ca7 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/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
index fd89428..bda354f 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 7a844f4..cd95ee9 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/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index d4e4c25..014c845 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 616fe98..928755d 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 7186dd7..80396c4 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/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
index b5c7d33..a7e4d9f 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 630473e..d3e2533 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 989b7d8..e7df3f8 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/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index be719ea..062d7ff 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/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index b45cc4d..4ab5a4a 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 f5458c1..46c9048 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
@@ -199,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;
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 52f46f2..a2625c4 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 a99e469..cb2f377 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);
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2965903..82508ad 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);
}
}
@@ -1189,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;
@@ -2595,7 +2592,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
@@ -2613,8 +2610,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)
@@ -2625,7 +2622,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);
@@ -3941,7 +3938,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();
}
@@ -3968,9 +3965,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/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index ed1503c..3750494 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -518,7 +518,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 c5cba8e..f5bd44d 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 d4fe5e0..5505001 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 a375da9..0bf23f1 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 eb386fe..296ab87 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/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index 8144870..e4a3382 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 0816b7b..8e40561 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 8ccfda5..d14edfd 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 dd9bbc1..4f4ff07 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/RegionConnections.cs b/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
index fba51d2..6bf1c4a 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 a5d8292..7d5c750 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2351,7 +2351,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;
}
@@ -2361,9 +2361,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
)
)
@@ -4654,10 +4654,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)
@@ -5948,7 +5945,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);
}
///
@@ -6103,7 +6100,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
{
@@ -6114,7 +6111,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 d2a5980..01d90e7 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 9cf7b35..8666421 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 7ee347c..d2fbfa6 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 8a31579..88d774a 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 3cf3416..312832f 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/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index 76415ce..eb44dcb 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 4024295..0448b54 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 19ea0fe..1119e48 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 f641955..da351b9 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 1c1c9b0..c833131 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 8e33373..fed7a16 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 52a17e7..84de47f 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
+}
--
cgit v1.1
From df14b40e88e658a2adb50d45c941fb016a2952eb Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sun, 29 Mar 2015 16:45:00 -0700
Subject: varregion: update LandManagementModule and LandObject for variable
sized regions.
---
.../CoreModules/World/Land/LandManagementModule.cs | 63 ++++----
.../Region/CoreModules/World/Land/LandObject.cs | 176 ++++++++++++---------
2 files changed, 133 insertions(+), 106 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 9279066..4aee6a5 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 a3cd4a5..5858d6c 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)
- {
- //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)
+ 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_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;
}
--
cgit v1.1
From 6081ae355456f8b7c361a9d4676376429518b0bf Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sun, 29 Mar 2015 16:55:18 -0700
Subject: varregion: update MapImageModule and ShadedMapTimeRenderer for
variable sized regions.
---
.../CoreModules/World/LegacyMap/MapImageModule.cs | 36 +++++++++++++---------
.../World/LegacyMap/ShadedMapTileRenderer.cs | 36 +++++++++++++---------
2 files changed, 43 insertions(+), 29 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index bc52a43..c7ffeaf 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 cb06fd4..708286c 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
+}
--
cgit v1.1
From c0ad5ee81da3d24153bfc9769759ac1981d604ea Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Sun, 29 Mar 2015 17:21:19 -0700
Subject: varregion: update MapImageServiceModule to upload multiple map tiles
for large regions.
---
.../MapImage/MapImageServiceModule.cs | 82 +++++++++++++++++-----
1 file changed, 65 insertions(+), 17 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 96182cd..da74f30 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())
- {
- mapTile.Save(stream, ImageFormat.Jpeg);
- jpgData = stream.ToArray();
- }
+ UploadMapTile(scene, mapTile);
}
+ }
+
+ private void ConvertAndUploadMaptile(Image tileImage, IScene scene, uint locX, uint locY)
+ {
+ byte[] jpgData = Utils.EmptyBytes;
- if (jpgData == Utils.EmptyBytes)
+ using (MemoryStream stream = new MemoryStream())
{
- m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed");
- return;
+ tileImage.Save(stream, ImageFormat.Jpeg);
+ jpgData = stream.ToArray();
}
-
- string reason = string.Empty;
- if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, scene.RegionInfo.ScopeID, out reason))
+ if (jpgData != Utils.EmptyBytes)
+ {
+ string reason = string.Empty;
+ if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, scene.RegionInfo.ScopeID, out reason))
+ {
+ m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
+ scene.RegionInfo.RegionName, locX, locY, reason);
+ }
+ }
+ else
{
- 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);
}
}
}
--
cgit v1.1