Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
0eaca7aafb
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue