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,

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);
}
}
@ -523,6 +532,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
// ITerrainModule.PushTerrain()
public void PushTerrain(IClientAPI pClient)
{
if (m_sendTerrainUpdatesByViewDistance)
{
ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
if (presence != null)
@ -540,6 +551,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
}
}
else
{
// The traditional way is to call into the protocol stack to send them all.
pClient.SendLayerData(new float[10]);
}
}
#region Plugin Loading Methods
@ -948,6 +965,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
/// <param name="x">The patch corner to send</param>
/// <param name="y">The patch corner to send</param>
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)
@ -966,6 +985,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
);
}
}
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);
}
);
}
}
private class PatchesToSend : IComparable<PatchesToSend>
{
@ -993,16 +1028,14 @@ 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())
{
if (m_sendTerrainUpdatesByViewDistance)
{
// There is something that could be sent to this client.
List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
if (toSend.Count > 0)
@ -1030,11 +1063,80 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
}
if (pups.sendAll && toSend.Count < 1024)
SendAllModifiedPatchs(pups);
}
Monitor.Exit(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;
}
}
}
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);
}
}
private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
{
@ -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;