recover opensim m_sendTerrainUpdatesByViewDistance. if false do as opensim (slower since it depended on sending terrain as TASK). if true send by view range and also all terrain at arrival

avinationmerge
UbitUmarov 2015-09-07 11:23:00 +01:00
parent abd6640453
commit 7276a89ddd
2 changed files with 189 additions and 56 deletions

View File

@ -1242,14 +1242,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
try try
{ {
// Send LayerData in typerwriter pattern // Send LayerData in typerwriter pattern
//for (int y = 0; y < 16; y++)
//{
// for (int x = 0; x < 16; x++)
// {
// SendLayerData(x, y, map);
// }
//}
for (int y = 0; y < 16; y++) // Send LayerData in a spiral pattern. Fun!
{ SendLayerTopRight(map, 0, 0, map.SizeX / Constants.TerrainPatchSize - 1, map.SizeY / Constants.TerrainPatchSize - 1);
for (int x = 0; x < 16; x++)
{
SendLayerData(x, y, map);
}
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -1257,6 +1259,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
} }
private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2)
{
// Row
for (int i = x1; i <= x2; i++)
SendLayerData(i, y1, map);
// Column
for (int j = y1 + 1; j <= y2; j++)
SendLayerData(x2, j, map);
if (x2 - x1 > 0 && y2 - y1 > 0)
SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
}
void SendLayerBottomLeft(TerrainData map, int x1, int y1, int x2, int y2)
{
// Row in reverse
for (int i = x2; i >= x1; i--)
SendLayerData(i, y2, map);
// Column in reverse
for (int j = y2 - 1; j >= y1; j--)
SendLayerData(x1, j, map);
if (x2 - x1 > 0 && y2 - y1 > 0)
SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
}
// Legacy form of invocation that passes around a bare data array. // 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. // 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, // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI,
@ -1359,7 +1390,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private void SendTheLayerPacket(LayerDataPacket layerpack) private void SendTheLayerPacket(LayerDataPacket layerpack)
{ {
OutPacket(layerpack, ThrottleOutPacketType.Land); OutPacket(layerpack, ThrottleOutPacketType.Land);
} }
/// <summary> /// <summary>

View File

@ -107,6 +107,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private bool[,] updated; // for each patch, whether it needs to be sent to this client 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 private int updateCount; // number of patches that need to be sent
public ScenePresence Presence; // a reference to the client to send to public ScenePresence Presence; // a reference to the client to send to
public bool sendAll;
public int sendAllcurrentX;
public int sendAllcurrentY;
public PatchUpdates(TerrainData terrData, ScenePresence pPresence) public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
{ {
@ -150,6 +154,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
updated[xx, yy] = state; updated[xx, yy] = state;
if (state) if (state)
updateCount = updated.GetLength(0) * updated.GetLength(1); updateCount = updated.GetLength(0) * updated.GetLength(1);
sendAllcurrentX = 0;
sendAllcurrentY = 0;
sendAll = true;
} }
// Logically OR's the terrain data's patch taint map into this client's update map. // Logically OR's the terrain data's patch taint map into this client's update map.
@ -211,7 +218,9 @@ namespace OpenSim.Region.CoreModules.World.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); m_sendTerrainUpdatesByViewDistance =
terrainConfig.GetBoolean(
"SendTerrainUpdatesByViewDistance",m_sendTerrainUpdatesByViewDistance);
} }
} }
@ -524,21 +533,29 @@ namespace OpenSim.Region.CoreModules.World.Terrain
// ITerrainModule.PushTerrain() // ITerrainModule.PushTerrain()
public void PushTerrain(IClientAPI pClient) public void PushTerrain(IClientAPI pClient)
{ {
ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); if (m_sendTerrainUpdatesByViewDistance)
if (presence != null)
{ {
lock (m_perClientPatchUpdates) ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
if (presence != null)
{ {
PatchUpdates pups; lock (m_perClientPatchUpdates)
if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
{ {
// There is a ScenePresence without a send patch map. Create one. PatchUpdates pups;
pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence); if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
m_perClientPatchUpdates.Add(presence.UUID, 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);
} }
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
@ -949,19 +966,37 @@ 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)
{ {
// Add that this patch needs to be sent to the accounting for each client. if (m_sendTerrainUpdatesByViewDistance)
lock (m_perClientPatchUpdates)
{ {
m_scene.ForEachScenePresence(presence => // Add that this patch needs to be sent to the accounting for each client.
{ lock (m_perClientPatchUpdates)
PatchUpdates thisClientUpdates; {
if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) m_scene.ForEachScenePresence(presence =>
{ {
// There is a ScenePresence without a send patch map. Create one. PatchUpdates thisClientUpdates;
thisClientUpdates = new PatchUpdates(terrData, presence); if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
m_perClientPatchUpdates.Add(presence.UUID, 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);
} }
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 that is passed is ignored so this passes a dummy heightmap.
//float[] heightMap = terrData.GetFloatsSerialized();
float[] heightMap = new float[10];
m_scene.ForEachClient(
delegate (IClientAPI controller)
{
controller.SendLayerData(x / Constants.TerrainPatchSize,
y / Constants.TerrainPatchSize,
heightMap);
} }
); );
} }
@ -993,46 +1028,113 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{ {
foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
{ {
if (!Monitor.TryEnter(pups))
continue;
// throught acording to land queue free to send bytes // throught acording to land queue free to send bytes
if (!pups.Presence.ControllingClient.CanSendLayerData()) if (!pups.Presence.ControllingClient.CanSendLayerData())
continue; continue;
if (pups.HasUpdates()) if (pups.HasUpdates())
{ {
if (m_sendTerrainUpdatesByViewDistance)
// 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}", // There is something that could be sent to this client.
// LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName); List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
// Sort the patches to send by the distance from the presence if (toSend.Count > 0)
toSend.Sort();
/*
foreach (PatchesToSend pts in toSend)
{ {
pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null); // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
// presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land); // 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[] xPieces = new int[toSend.Count];
int[] yPieces = new int[toSend.Count]; int[] yPieces = new int[toSend.Count];
float[] patchPieces = new float[toSend.Count * 2]; float[] patchPieces = new float[toSend.Count * 2];
int pieceIndex = 0; int pieceIndex = 0;
foreach (PatchesToSend pts in toSend) foreach (PatchesToSend pts in toSend)
{ {
patchPieces[pieceIndex++] = pts.PatchX; patchPieces[pieceIndex++] = pts.PatchX;
patchPieces[pieceIndex++] = pts.PatchY; patchPieces[pieceIndex++] = pts.PatchY;
}
pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
} }
pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces); if (pups.sendAll && toSend.Count < 1024)
SendAllModifiedPatchs(pups);
}
else
SendAllModifiedPatchs(pups);
}
}
}
}
private void SendAllModifiedPatchs(PatchUpdates pups)
{
if (!pups.sendAll) // sanity
return;
int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
if (pups.sendAllcurrentX > limitX || pups.sendAllcurrentY > limitY)
{
pups.sendAll = false;
pups.sendAllcurrentX = 0;
pups.sendAllcurrentY = 0;
return;
}
int npatchs = 0;
List<PatchesToSend> patchs = new List<PatchesToSend>();
int x = pups.sendAllcurrentX;
int y = pups.sendAllcurrentY;
// send it in the order viewer draws it
// even if not best for memory scan
for (; y < limitY; y++)
{
for (; x < limitX; x++)
{
if (pups.GetByPatch(x, y))
{
pups.SetByPatch(x, y, false);
patchs.Add(new PatchesToSend(x, y, 0));
if (++npatchs >= 512)
{
pups.sendAllcurrentX = x + 1;
pups.sendAllcurrentY = y;
break;
} }
} }
Monitor.Exit(pups);
} }
if (npatchs >= 512)
break;
x = 0;
}
if (x >= limitX && y >= limitY)
{
pups.sendAll = false;
pups.sendAllcurrentX = 0;
pups.sendAllcurrentY = 0;
}
npatchs = patchs.Count;
if (npatchs > 0)
{
int[] xPieces = new int[npatchs];
int[] yPieces = new int[npatchs];
float[] patchPieces = new float[npatchs * 2];
int pieceIndex = 0;
foreach (PatchesToSend pts in patchs)
{
patchPieces[pieceIndex++] = pts.PatchX;
patchPieces[pieceIndex++] = pts.PatchY;
}
pups.Presence.ControllingClient.SendLayerData(-npatchs, 0, patchPieces);
} }
} }
@ -1119,7 +1221,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
{ {
pups.SetByPatch(x, y, false); pups.SetByPatch(x, y, false);
ret.Add(new PatchesToSend(x, y, (float)distsq)); ret.Add(new PatchesToSend(x, y, (float)distsq));
if (npatchs++ > 65536) if (npatchs++ > 1024)
{ {
y = endY; y = endY;
x = endX; x = endX;