Merge branch 'master' of ssh://opensimulator.org/var/git/opensim

bullet-2.82
Diva Canto 2014-06-01 10:06:59 -07:00
commit 0eaca7aafb
9 changed files with 381 additions and 81 deletions

View File

@ -820,7 +820,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
agentCircuit.Id0 = currentAgentCircuit.Id0; agentCircuit.Id0 = currentAgentCircuit.Id0;
} }
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) // if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
if (NeedsNewAgent(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
{ {
// brand new agent, let's create a new caps seed // brand new agent, let's create a new caps seed
agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
@ -894,7 +895,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
IClientIPEndpoint ipepClient; IClientIPEndpoint ipepClient;
string capsPath = String.Empty; string capsPath = String.Empty;
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) if (NeedsNewAgent(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
@ -1070,7 +1071,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
{ {
if (!sp.Scene.IncomingPreCloseClient(sp)) if (!sp.Scene.IncomingPreCloseClient(sp))
return; return;
@ -1140,7 +1141,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
IClientIPEndpoint ipepClient; IClientIPEndpoint ipepClient;
string capsPath = String.Empty; string capsPath = String.Empty;
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) if (NeedsNewAgent(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}", "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
@ -1236,7 +1237,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.MakeChildAgent(); sp.MakeChildAgent();
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
{ {
if (!sp.Scene.IncomingPreCloseClient(sp)) if (!sp.Scene.IncomingPreCloseClient(sp))
return; return;
@ -2366,7 +2367,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{ {
// The area to check is as big as the current region. // The area to check is as big as the current region.
// We presume all adjacent regions are the same size as this region. // We presume all adjacent regions are the same size as this region.
uint dd = Math.Max((uint)avatar.DrawDistance, uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY)); Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2; uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;

View File

@ -199,6 +199,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
{ {
GridRegion region = null; GridRegion region = null;
uint regionX = Util.WorldToRegionLoc((uint)x);
uint regionY = Util.WorldToRegionLoc((uint)y);
// First see if it's a neighbour, even if it isn't on this sim. // First see if it's a neighbour, even if it isn't on this sim.
// Neighbour data is cached in memory, so this is fast // Neighbour data is cached in memory, so this is fast
@ -222,11 +224,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
{ {
region = m_GridService.GetRegionByPosition(scopeID, x, y); region = m_GridService.GetRegionByPosition(scopeID, x, y);
if (region == null) if (region == null)
{
m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>", m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>",
LogHeader, x, y); LogHeader, regionX, regionY);
}
else else
{
m_log.DebugFormat("{0} GetRegionByPosition. Requested region {1} from grid service. Pos=<{2},{3}>", m_log.DebugFormat("{0} GetRegionByPosition. Requested region {1} from grid service. Pos=<{2},{3}>",
LogHeader, region.RegionName, x, y); LogHeader, region.RegionName, regionX, regionY);
}
} }
return region; return region;
} }

View File

@ -99,6 +99,85 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private String m_InitialTerrain = "pinhead-island"; private String m_InitialTerrain = "pinhead-island";
// If true, send terrain patch updates to clients based on their view distance
private bool m_sendTerrainUpdatesByViewDistance = false;
// 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<UUID, PatchUpdates> m_perClientPatchUpdates = new Dictionary<UUID, PatchUpdates>();
/// <summary> /// <summary>
/// Human readable list of terrain file extensions that are supported. /// Human readable list of terrain file extensions that are supported.
/// </summary> /// </summary>
@ -127,7 +206,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{ {
IConfig terrainConfig = config.Configs["Terrain"]; IConfig terrainConfig = config.Configs["Terrain"];
if (terrainConfig != null) if (terrainConfig != null)
{
m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance);
}
} }
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
@ -422,9 +504,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 () public void TaintTerrain ()
{ {
m_channel.GetTerrainData().TaintAllTerrain(); 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 #region Plugin Loading Methods
@ -676,6 +795,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
} }
} }
} }
// This event also causes changes to be sent to the clients
CheckSendingPatchesToClients();
// If things changes, generate some events
if (shouldTaint) if (shouldTaint)
{ {
m_scene.EventManager.TriggerTerrainTainted(); m_scene.EventManager.TriggerTerrainTainted();
@ -749,28 +873,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
presence.ControllingClient.OnLandUndo -= client_OnLandUndo; presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
} }
} if (m_perClientPatchUpdates.ContainsKey(client))
/// <summary>
/// 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
/// </summary>
private void CheckForTerrainUpdates()
{ {
CheckForTerrainUpdates(false); m_perClientPatchUpdates.Remove(client);
} }
/// <summary>
/// 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
/// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
/// </summary>
private void CheckForTerrainUpdates(bool respectEstateSettings)
{
} }
/// <summary> /// <summary>
@ -857,6 +963,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// <param name="y">The patch corner to send</param> /// <param name="y">The patch corner to send</param>
private void SendToClients(TerrainData terrData, 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. // We know the actual terrain data passed is ignored. This kludge saves changing IClientAPI.
//float[] heightMap = terrData.GetFloatsSerialized(); //float[] heightMap = terrData.GetFloatsSerialized();
float[] heightMap = new float[10]; float[] heightMap = new float[10];
@ -869,6 +997,107 @@ namespace OpenSim.Region.CoreModules.World.Terrain
} }
); );
} }
}
private class PatchesToSend : IComparable<PatchesToSend>
{
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<PatchesToSend> 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)
{
// TODO: one can send multiple patches in a packet. Do that.
pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
// presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
}
}
}
}
}
}
private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
{
List<PatchesToSend> ret = new List<PatchesToSend>();
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, private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
float north, float west, float south, float east, UUID agentId) float north, float west, float south, float east, UUID agentId)

View File

@ -24,9 +24,10 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.IO; using System.IO;
using OpenSim.Framework;
using OpenMetaverse; using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces namespace OpenSim.Region.Framework.Interfaces
@ -43,6 +44,12 @@ namespace OpenSim.Region.Framework.Interfaces
/// </summary> /// </summary>
void TaintTerrain(); void TaintTerrain();
/// <summary>
/// When a client initially connects, all the terrain must be pushed to the viewer.
/// This call causes all the terrain patches to be sent to the client.
/// </summary>
void PushTerrain(IClientAPI pClient);
/// <summary> /// <summary>
/// Load a terrain from a stream. /// Load a terrain from a stream.
/// </summary> /// </summary>

View File

@ -213,7 +213,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="RemoteClient">Client to send to</param> /// <param name="RemoteClient">Client to send to</param>
public virtual void SendLayerData(IClientAPI RemoteClient) public virtual void SendLayerData(IClientAPI RemoteClient)
{ {
RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); // RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised());
ITerrainModule terrModule = RequestModuleInterface<ITerrainModule>();
if (terrModule != null)
{
terrModule.PushTerrain(RemoteClient);
}
} }
#endregion #endregion

View File

@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes
public class SceneCommunicationService //one instance per region public class SceneCommunicationService //one instance per region
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[SCENE COMMUNIATION SERVICE]";
protected RegionInfo m_regionInfo; protected RegionInfo m_regionInfo;
protected Scene m_scene; protected Scene m_scene;
@ -84,15 +85,12 @@ namespace OpenSim.Region.Framework.Scenes
if (neighbourService != null) if (neighbourService != null)
neighbour = neighbourService.HelloNeighbour(regionhandle, region); neighbour = neighbourService.HelloNeighbour(regionhandle, region);
else else
m_log.DebugFormat( m_log.DebugFormat( "{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name);
"[SCENE COMMUNICATION SERVICE]: No neighbour service provided for region {0} to inform neigbhours of status",
m_scene.Name);
if (neighbour != null) if (neighbour != null)
{ {
m_log.DebugFormat( m_log.DebugFormat( "{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up",
"[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up", LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
m_scene.EventManager.TriggerOnRegionUp(neighbour); m_scene.EventManager.TriggerOnRegionUp(neighbour);
} }
@ -111,9 +109,7 @@ namespace OpenSim.Region.Framework.Scenes
List<GridRegion> neighbours List<GridRegion> neighbours
= m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
m_log.DebugFormat( m_log.DebugFormat("{0} Informing {1} neighbours that region {2} is up", LogHeader, neighbours.Count, m_scene.Name);
"[SCENE COMMUNICATION SERVICE]: Informing {0} neighbours that region {1} is up",
neighbours.Count, m_scene.Name);
foreach (GridRegion n in neighbours) foreach (GridRegion n in neighbours)
{ {

View File

@ -873,7 +873,8 @@ namespace OpenSim.Region.Framework.Scenes
m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
Animator = new ScenePresenceAnimator(this); Animator = new ScenePresenceAnimator(this);
PresenceType = type; PresenceType = type;
DrawDistance = world.DefaultDrawDistance; // DrawDistance = world.DefaultDrawDistance;
DrawDistance = Constants.RegionSize;
RegionHandle = world.RegionInfo.RegionHandle; RegionHandle = world.RegionInfo.RegionHandle;
ControllingClient = client; ControllingClient = client;
Firstname = ControllingClient.FirstName; Firstname = ControllingClient.FirstName;
@ -1918,8 +1919,8 @@ namespace OpenSim.Region.Framework.Scenes
// When we get to the point of re-computing neighbors everytime this // When we get to the point of re-computing neighbors everytime this
// changes, then start using the agent's drawdistance rather than the // changes, then start using the agent's drawdistance rather than the
// region's draw distance. // region's draw distance.
// DrawDistance = agentData.Far; DrawDistance = agentData.Far;
DrawDistance = Scene.DefaultDrawDistance; // DrawDistance = Scene.DefaultDrawDistance;
m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
@ -2277,8 +2278,8 @@ namespace OpenSim.Region.Framework.Scenes
// When we get to the point of re-computing neighbors everytime this // When we get to the point of re-computing neighbors everytime this
// changes, then start using the agent's drawdistance rather than the // changes, then start using the agent's drawdistance rather than the
// region's draw distance. // region's draw distance.
// DrawDistance = agentData.Far; DrawDistance = agentData.Far;
DrawDistance = Scene.DefaultDrawDistance; // DrawDistance = Scene.DefaultDrawDistance;
// Check if Client has camera in 'follow cam' or 'build' mode. // Check if Client has camera in 'follow cam' or 'build' mode.
Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
@ -3824,8 +3825,8 @@ namespace OpenSim.Region.Framework.Scenes
// When we get to the point of re-computing neighbors everytime this // When we get to the point of re-computing neighbors everytime this
// changes, then start using the agent's drawdistance rather than the // changes, then start using the agent's drawdistance rather than the
// region's draw distance. // region's draw distance.
// DrawDistance = cAgentData.Far; DrawDistance = cAgentData.Far;
DrawDistance = Scene.DefaultDrawDistance; // DrawDistance = Scene.DefaultDrawDistance;
if (cAgentData.Position != marker) // UGH!! if (cAgentData.Position != marker) // UGH!!
m_pos = cAgentData.Position + offset; m_pos = cAgentData.Position + offset;
@ -3935,8 +3936,8 @@ namespace OpenSim.Region.Framework.Scenes
// When we get to the point of re-computing neighbors everytime this // When we get to the point of re-computing neighbors everytime this
// changes, then start using the agent's drawdistance rather than the // changes, then start using the agent's drawdistance rather than the
// region's draw distance. // region's draw distance.
// DrawDistance = cAgent.Far; DrawDistance = cAgent.Far;
DrawDistance = Scene.DefaultDrawDistance; // DrawDistance = Scene.DefaultDrawDistance;
if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
ControllingClient.SetChildAgentThrottle(cAgent.Throttles); ControllingClient.SetChildAgentThrottle(cAgent.Throttles);

View File

@ -46,6 +46,7 @@ namespace OpenSim.Services.GridService
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger( LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
private string LogHeader = "[GRID SERVICE]";
private bool m_DeleteOnUnregister = true; private bool m_DeleteOnUnregister = true;
private static GridService m_RootInstance = null; private static GridService m_RootInstance = null;
@ -328,7 +329,11 @@ namespace OpenSim.Services.GridService
} }
} }
// m_log.DebugFormat("[GRID SERVICE]: region {0} has {1} neighbours", region.RegionName, rinfos.Count); // string rNames = "";
// foreach (GridRegion gr in rinfos)
// rNames += gr.RegionName + ",";
// m_log.DebugFormat("{0} region {1} has {2} neighbours ({3})",
// LogHeader, region.RegionName, rinfos.Count, rNames);
} }
else else
{ {

View File

@ -36,6 +36,7 @@ using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using System.Threading;
using Nini.Config; using Nini.Config;
using log4net; using log4net;
@ -53,6 +54,7 @@ namespace OpenSim.Services.MapImageService
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger( LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
private string LogHeader = "[MAP IMAGE SERVICE]";
private const int ZOOM_LEVELS = 8; private const int ZOOM_LEVELS = 8;
private const int IMAGE_WIDTH = 256; private const int IMAGE_WIDTH = 256;
@ -114,7 +116,7 @@ namespace OpenSim.Services.MapImageService
} }
} }
return UpdateMultiResolutionFiles(x, y, out reason); return UpdateMultiResolutionFilesAsync(x, y, out reason);
} }
public bool RemoveMapTile(int x, int y, out string reason) public bool RemoveMapTile(int x, int y, out string reason)
@ -136,14 +138,59 @@ namespace OpenSim.Services.MapImageService
} }
} }
return UpdateMultiResolutionFiles(x, y, out reason); return UpdateMultiResolutionFilesAsync(x, y, out reason);
} }
private bool UpdateMultiResolutionFiles(int x, int y, out string reason) // When large varregions start up, they can send piles of new map tiles. This causes
// this multi-resolution routine to be called a zillion times an causes much CPU
// time to be spent creating multi-resolution tiles that will be replaced when
// the next maptile arrives.
private class mapToMultiRez
{
public int xx;
public int yy;
public mapToMultiRez(int pX, int pY)
{
xx = pX;
yy = pY;
}
};
private Queue<mapToMultiRez> multiRezToBuild = new Queue<mapToMultiRez>();
private bool UpdateMultiResolutionFilesAsync(int x, int y, out string reason)
{ {
reason = String.Empty; reason = String.Empty;
lock (m_Sync) lock (multiRezToBuild)
{ {
// m_log.DebugFormat("{0} UpdateMultiResolutionFilesAsync: scheduling update for <{1},{2}>", LogHeader, x, y);
multiRezToBuild.Enqueue(new mapToMultiRez(x, y));
if (multiRezToBuild.Count == 1)
Util.FireAndForget(DoUpdateMultiResolutionFilesAsync);
}
return true;
}
private void DoUpdateMultiResolutionFilesAsync(object o)
{
// This sleep causes the FireAndForget thread to be different than the invocation thread.
// It also allows other tiles to be uploaded so the multi-rez images are more likely
// to be correct.
Thread.Sleep(1 * 1000);
while (multiRezToBuild.Count > 0)
{
mapToMultiRez toMultiRez = null;
lock (multiRezToBuild)
{
if (multiRezToBuild.Count > 0)
toMultiRez = multiRezToBuild.Dequeue();
}
if (toMultiRez != null)
{
int x = toMultiRez.xx;
int y = toMultiRez.yy;
// m_log.DebugFormat("{0} DoUpdateMultiResolutionFilesAsync: doing build for <{1},{2}>", LogHeader, x, y);
// Stitch seven more aggregate tiles together // Stitch seven more aggregate tiles together
for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
{ {
@ -153,16 +200,19 @@ namespace OpenSim.Services.MapImageService
int x1 = x - (x % width); int x1 = x - (x % width);
int y1 = y - (y % width); int y1 = y - (y % width);
lock (m_Sync) // must lock the reading and writing of the maptile files
{
if (!CreateTile(zoomLevel, x1, y1)) if (!CreateTile(zoomLevel, x1, y1))
{ {
m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel); m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel);
reason = string.Format("Map tile at zoom level {0} failed", zoomLevel); return;
return false; }
}
} }
} }
} }
return true; return;
} }
public byte[] GetMapTile(string fileName, out string format) public byte[] GetMapTile(string fileName, out string format)