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
{
// 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++)
{
for (int x = 0; x < 16; x++)
{
SendLayerData(x, y, map);
}
}
// Send LayerData in a spiral pattern. Fun!
SendLayerTopRight(map, 0, 0, map.SizeX / Constants.TerrainPatchSize - 1, map.SizeY / Constants.TerrainPatchSize - 1);
}
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.
// 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,
@ -1359,7 +1390,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private void SendTheLayerPacket(LayerDataPacket layerpack)
{
OutPacket(layerpack, ThrottleOutPacketType.Land);
OutPacket(layerpack, ThrottleOutPacketType.Land);
}
/// <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 int updateCount; // number of patches that need to be sent
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)
{
@ -150,6 +154,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
updated[xx, yy] = state;
if (state)
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.
@ -211,7 +218,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (terrainConfig != null)
{
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()
public void PushTerrain(IClientAPI pClient)
{
ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
if (presence != null)
if (m_sendTerrainUpdatesByViewDistance)
{
lock (m_perClientPatchUpdates)
ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
if (presence != null)
{
PatchUpdates pups;
if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
lock (m_perClientPatchUpdates)
{
// 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);
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);
}
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
@ -949,19 +966,37 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// <param name="y">The patch corner to send</param>
private void SendToClients(TerrainData terrData, int x, int y)
{
// Add that this patch needs to be sent to the accounting for each client.
lock (m_perClientPatchUpdates)
if (m_sendTerrainUpdatesByViewDistance)
{
m_scene.ForEachScenePresence(presence =>
{
PatchUpdates thisClientUpdates;
if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
// Add that this patch needs to be sent to the accounting for each client.
lock (m_perClientPatchUpdates)
{
m_scene.ForEachScenePresence(presence =>
{
// There is a ScenePresence without a send patch map. Create one.
thisClientUpdates = new PatchUpdates(terrData, presence);
m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
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);
}
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)
{
if (!Monitor.TryEnter(pups))
continue;
// throught acording to land queue free to send bytes
if (!pups.Presence.ControllingClient.CanSendLayerData())
continue;
if (pups.HasUpdates())
{
// There is something that could be sent to this client.
List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
if (toSend.Count > 0)
if (m_sendTerrainUpdatesByViewDistance)
{
// 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)
// There is something that could be sent to this client.
List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
if (toSend.Count > 0)
{
pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
// presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
}
*/
// 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;
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);
}
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);
ret.Add(new PatchesToSend(x, y, (float)distsq));
if (npatchs++ > 65536)
if (npatchs++ > 1024)
{
y = endY;
x = endX;