aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs47
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs198
2 files changed, 189 insertions, 56 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 6df55a6..7c5aee7 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -1242,14 +1242,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1242 try 1242 try
1243 { 1243 {
1244 // Send LayerData in typerwriter pattern 1244 // Send LayerData in typerwriter pattern
1245 //for (int y = 0; y < 16; y++)
1246 //{
1247 // for (int x = 0; x < 16; x++)
1248 // {
1249 // SendLayerData(x, y, map);
1250 // }
1251 //}
1245 1252
1246 for (int y = 0; y < 16; y++) 1253 // Send LayerData in a spiral pattern. Fun!
1247 { 1254 SendLayerTopRight(map, 0, 0, map.SizeX / Constants.TerrainPatchSize - 1, map.SizeY / Constants.TerrainPatchSize - 1);
1248 for (int x = 0; x < 16; x++)
1249 {
1250 SendLayerData(x, y, map);
1251 }
1252 }
1253 } 1255 }
1254 catch (Exception e) 1256 catch (Exception e)
1255 { 1257 {
@@ -1257,6 +1259,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1257 } 1259 }
1258 } 1260 }
1259 1261
1262 private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2)
1263 {
1264 // Row
1265 for (int i = x1; i <= x2; i++)
1266 SendLayerData(i, y1, map);
1267
1268 // Column
1269 for (int j = y1 + 1; j <= y2; j++)
1270 SendLayerData(x2, j, map);
1271
1272 if (x2 - x1 > 0 && y2 - y1 > 0)
1273 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1274 }
1275
1276 void SendLayerBottomLeft(TerrainData map, int x1, int y1, int x2, int y2)
1277 {
1278 // Row in reverse
1279 for (int i = x2; i >= x1; i--)
1280 SendLayerData(i, y2, map);
1281
1282 // Column in reverse
1283 for (int j = y2 - 1; j >= y1; j--)
1284 SendLayerData(x1, j, map);
1285
1286 if (x2 - x1 > 0 && y2 - y1 > 0)
1287 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1288 }
1289
1290
1260 // Legacy form of invocation that passes around a bare data array. 1291 // Legacy form of invocation that passes around a bare data array.
1261 // Just ignore what was passed and use the real terrain info that is part of the scene. 1292 // Just ignore what was passed and use the real terrain info that is part of the scene.
1262 // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI, 1293 // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI,
@@ -1359,7 +1390,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1359 1390
1360 private void SendTheLayerPacket(LayerDataPacket layerpack) 1391 private void SendTheLayerPacket(LayerDataPacket layerpack)
1361 { 1392 {
1362 OutPacket(layerpack, ThrottleOutPacketType.Land); 1393 OutPacket(layerpack, ThrottleOutPacketType.Land);
1363 } 1394 }
1364 1395
1365 /// <summary> 1396 /// <summary>
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index e3a0825..2f4618d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -107,6 +107,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
107 private bool[,] updated; // for each patch, whether it needs to be sent to this client 107 private bool[,] updated; // for each patch, whether it needs to be sent to this client
108 private int updateCount; // number of patches that need to be sent 108 private int updateCount; // number of patches that need to be sent
109 public ScenePresence Presence; // a reference to the client to send to 109 public ScenePresence Presence; // a reference to the client to send to
110 public bool sendAll;
111 public int sendAllcurrentX;
112 public int sendAllcurrentY;
113
110 114
111 public PatchUpdates(TerrainData terrData, ScenePresence pPresence) 115 public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
112 { 116 {
@@ -150,6 +154,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
150 updated[xx, yy] = state; 154 updated[xx, yy] = state;
151 if (state) 155 if (state)
152 updateCount = updated.GetLength(0) * updated.GetLength(1); 156 updateCount = updated.GetLength(0) * updated.GetLength(1);
157 sendAllcurrentX = 0;
158 sendAllcurrentY = 0;
159 sendAll = true;
153 } 160 }
154 161
155 // Logically OR's the terrain data's patch taint map into this client's update map. 162 // 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
211 if (terrainConfig != null) 218 if (terrainConfig != null)
212 { 219 {
213 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 220 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
214 m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance); 221 m_sendTerrainUpdatesByViewDistance =
222 terrainConfig.GetBoolean(
223 "SendTerrainUpdatesByViewDistance",m_sendTerrainUpdatesByViewDistance);
215 } 224 }
216 } 225 }
217 226
@@ -524,21 +533,29 @@ namespace OpenSim.Region.CoreModules.World.Terrain
524 // ITerrainModule.PushTerrain() 533 // ITerrainModule.PushTerrain()
525 public void PushTerrain(IClientAPI pClient) 534 public void PushTerrain(IClientAPI pClient)
526 { 535 {
527 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 536 if (m_sendTerrainUpdatesByViewDistance)
528 if (presence != null)
529 { 537 {
530 lock (m_perClientPatchUpdates) 538 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
539 if (presence != null)
531 { 540 {
532 PatchUpdates pups; 541 lock (m_perClientPatchUpdates)
533 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
534 { 542 {
535 // There is a ScenePresence without a send patch map. Create one. 543 PatchUpdates pups;
536 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence); 544 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
537 m_perClientPatchUpdates.Add(presence.UUID, pups); 545 {
546 // There is a ScenePresence without a send patch map. Create one.
547 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
548 m_perClientPatchUpdates.Add(presence.UUID, pups);
549 }
550 pups.SetAll(true);
538 } 551 }
539 pups.SetAll(true);
540 } 552 }
541 } 553 }
554 else
555 {
556 // The traditional way is to call into the protocol stack to send them all.
557 pClient.SendLayerData(new float[10]);
558 }
542 } 559 }
543 560
544 #region Plugin Loading Methods 561 #region Plugin Loading Methods
@@ -949,19 +966,37 @@ namespace OpenSim.Region.CoreModules.World.Terrain
949 /// <param name="y">The patch corner to send</param> 966 /// <param name="y">The patch corner to send</param>
950 private void SendToClients(TerrainData terrData, int x, int y) 967 private void SendToClients(TerrainData terrData, int x, int y)
951 { 968 {
952 // Add that this patch needs to be sent to the accounting for each client. 969 if (m_sendTerrainUpdatesByViewDistance)
953 lock (m_perClientPatchUpdates)
954 { 970 {
955 m_scene.ForEachScenePresence(presence => 971 // Add that this patch needs to be sent to the accounting for each client.
956 { 972 lock (m_perClientPatchUpdates)
957 PatchUpdates thisClientUpdates; 973 {
958 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) 974 m_scene.ForEachScenePresence(presence =>
959 { 975 {
960 // There is a ScenePresence without a send patch map. Create one. 976 PatchUpdates thisClientUpdates;
961 thisClientUpdates = new PatchUpdates(terrData, presence); 977 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
962 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates); 978 {
979 // There is a ScenePresence without a send patch map. Create one.
980 thisClientUpdates = new PatchUpdates(terrData, presence);
981 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
982 }
983 thisClientUpdates.SetByXY(x, y, true);
963 } 984 }
964 thisClientUpdates.SetByXY(x, y, true); 985 );
986 }
987 }
988 else
989 {
990 // Legacy update sending where the update is sent out as soon as noticed
991 // We know the actual terrain data that is passed is ignored so this passes a dummy heightmap.
992 //float[] heightMap = terrData.GetFloatsSerialized();
993 float[] heightMap = new float[10];
994 m_scene.ForEachClient(
995 delegate (IClientAPI controller)
996 {
997 controller.SendLayerData(x / Constants.TerrainPatchSize,
998 y / Constants.TerrainPatchSize,
999 heightMap);
965 } 1000 }
966 ); 1001 );
967 } 1002 }
@@ -993,46 +1028,113 @@ namespace OpenSim.Region.CoreModules.World.Terrain
993 { 1028 {
994 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) 1029 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
995 { 1030 {
996 if (!Monitor.TryEnter(pups))
997 continue;
998
999 // throught acording to land queue free to send bytes 1031 // throught acording to land queue free to send bytes
1000 if (!pups.Presence.ControllingClient.CanSendLayerData()) 1032 if (!pups.Presence.ControllingClient.CanSendLayerData())
1001 continue; 1033 continue;
1002 1034
1003 if (pups.HasUpdates()) 1035 if (pups.HasUpdates())
1004 { 1036 {
1005 1037 if (m_sendTerrainUpdatesByViewDistance)
1006 // There is something that could be sent to this client.
1007 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1008 if (toSend.Count > 0)
1009 { 1038 {
1010 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}", 1039 // There is something that could be sent to this client.
1011 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName); 1040 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1012 // Sort the patches to send by the distance from the presence 1041 if (toSend.Count > 0)
1013 toSend.Sort();
1014 /*
1015 foreach (PatchesToSend pts in toSend)
1016 { 1042 {
1017 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null); 1043 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
1018 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land); 1044 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
1045 // Sort the patches to send by the distance from the presence
1046 toSend.Sort();
1047 /*
1048 foreach (PatchesToSend pts in toSend)
1049 {
1050 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1051 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1052 }
1053 */
1054
1055 int[] xPieces = new int[toSend.Count];
1056 int[] yPieces = new int[toSend.Count];
1057 float[] patchPieces = new float[toSend.Count * 2];
1058 int pieceIndex = 0;
1059 foreach (PatchesToSend pts in toSend)
1060 {
1061 patchPieces[pieceIndex++] = pts.PatchX;
1062 patchPieces[pieceIndex++] = pts.PatchY;
1063 }
1064 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
1019 } 1065 }
1020 */ 1066 if (pups.sendAll && toSend.Count < 1024)
1067 SendAllModifiedPatchs(pups);
1068 }
1069 else
1070 SendAllModifiedPatchs(pups);
1071 }
1072 }
1073 }
1074 }
1075 private void SendAllModifiedPatchs(PatchUpdates pups)
1076 {
1077 if (!pups.sendAll) // sanity
1078 return;
1021 1079
1022 int[] xPieces = new int[toSend.Count]; 1080 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1023 int[] yPieces = new int[toSend.Count]; 1081 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1024 float[] patchPieces = new float[toSend.Count * 2]; 1082
1025 int pieceIndex = 0; 1083 if (pups.sendAllcurrentX > limitX || pups.sendAllcurrentY > limitY)
1026 foreach (PatchesToSend pts in toSend) 1084 {
1027 { 1085 pups.sendAll = false;
1028 patchPieces[pieceIndex++] = pts.PatchX; 1086 pups.sendAllcurrentX = 0;
1029 patchPieces[pieceIndex++] = pts.PatchY; 1087 pups.sendAllcurrentY = 0;
1030 } 1088 return;
1031 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces); 1089 }
1090
1091 int npatchs = 0;
1092 List<PatchesToSend> patchs = new List<PatchesToSend>();
1093 int x = pups.sendAllcurrentX;
1094 int y = pups.sendAllcurrentY;
1095 // send it in the order viewer draws it
1096 // even if not best for memory scan
1097 for (; y < limitY; y++)
1098 {
1099 for (; x < limitX; x++)
1100 {
1101 if (pups.GetByPatch(x, y))
1102 {
1103 pups.SetByPatch(x, y, false);
1104 patchs.Add(new PatchesToSend(x, y, 0));
1105 if (++npatchs >= 512)
1106 {
1107 pups.sendAllcurrentX = x + 1;
1108 pups.sendAllcurrentY = y;
1109 break;
1032 } 1110 }
1033 } 1111 }
1034 Monitor.Exit(pups);
1035 } 1112 }
1113 if (npatchs >= 512)
1114 break;
1115 x = 0;
1116 }
1117
1118 if (x >= limitX && y >= limitY)
1119 {
1120 pups.sendAll = false;
1121 pups.sendAllcurrentX = 0;
1122 pups.sendAllcurrentY = 0;
1123 }
1124
1125 npatchs = patchs.Count;
1126 if (npatchs > 0)
1127 {
1128 int[] xPieces = new int[npatchs];
1129 int[] yPieces = new int[npatchs];
1130 float[] patchPieces = new float[npatchs * 2];
1131 int pieceIndex = 0;
1132 foreach (PatchesToSend pts in patchs)
1133 {
1134 patchPieces[pieceIndex++] = pts.PatchX;
1135 patchPieces[pieceIndex++] = pts.PatchY;
1136 }
1137 pups.Presence.ControllingClient.SendLayerData(-npatchs, 0, patchPieces);
1036 } 1138 }
1037 } 1139 }
1038 1140
@@ -1119,7 +1221,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1119 { 1221 {
1120 pups.SetByPatch(x, y, false); 1222 pups.SetByPatch(x, y, false);
1121 ret.Add(new PatchesToSend(x, y, (float)distsq)); 1223 ret.Add(new PatchesToSend(x, y, (float)distsq));
1122 if (npatchs++ > 65536) 1224 if (npatchs++ > 1024)
1123 { 1225 {
1124 y = endY; 1226 y = endY;
1125 x = endX; 1227 x = endX;