aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs295
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainModule.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs19
-rw-r--r--OpenSim/Services/GridService/GridService.cs9
-rw-r--r--OpenSim/Services/MapImageService/MapImageService.cs82
9 files changed, 379 insertions, 79 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index e583590..70b0e0a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -820,7 +820,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
820 agentCircuit.Id0 = currentAgentCircuit.Id0; 820 agentCircuit.Id0 = currentAgentCircuit.Id0;
821 } 821 }
822 822
823 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 823 // if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
824 if (NeedsNewAgent(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
824 { 825 {
825 // brand new agent, let's create a new caps seed 826 // brand new agent, let's create a new caps seed
826 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 827 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
@@ -894,7 +895,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
894 895
895 IClientIPEndpoint ipepClient; 896 IClientIPEndpoint ipepClient;
896 string capsPath = String.Empty; 897 string capsPath = String.Empty;
897 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 898 if (NeedsNewAgent(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
898 { 899 {
899 m_log.DebugFormat( 900 m_log.DebugFormat(
900 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", 901 "[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
1070 1071
1071 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1072 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1072 1073
1073 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1074 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1074 { 1075 {
1075 if (!sp.Scene.IncomingPreCloseClient(sp)) 1076 if (!sp.Scene.IncomingPreCloseClient(sp))
1076 return; 1077 return;
@@ -1140,7 +1141,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1140 1141
1141 IClientIPEndpoint ipepClient; 1142 IClientIPEndpoint ipepClient;
1142 string capsPath = String.Empty; 1143 string capsPath = String.Empty;
1143 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 1144 if (NeedsNewAgent(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
1144 { 1145 {
1145 m_log.DebugFormat( 1146 m_log.DebugFormat(
1146 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}", 1147 "[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
1236 sp.MakeChildAgent(); 1237 sp.MakeChildAgent();
1237 1238
1238 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1239 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1239 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1240 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1240 { 1241 {
1241 if (!sp.Scene.IncomingPreCloseClient(sp)) 1242 if (!sp.Scene.IncomingPreCloseClient(sp))
1242 return; 1243 return;
@@ -2366,7 +2367,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2366 { 2367 {
2367 // The area to check is as big as the current region. 2368 // The area to check is as big as the current region.
2368 // We presume all adjacent regions are the same size as this region. 2369 // We presume all adjacent regions are the same size as this region.
2369 uint dd = Math.Max((uint)avatar.DrawDistance, 2370 uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
2370 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY)); 2371 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2371 2372
2372 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2; 2373 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 3b38c71..d5fca71 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -199,6 +199,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
199 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 199 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
200 { 200 {
201 GridRegion region = null; 201 GridRegion region = null;
202 uint regionX = Util.WorldToRegionLoc((uint)x);
203 uint regionY = Util.WorldToRegionLoc((uint)y);
202 204
203 // First see if it's a neighbour, even if it isn't on this sim. 205 // First see if it's a neighbour, even if it isn't on this sim.
204 // Neighbour data is cached in memory, so this is fast 206 // Neighbour data is cached in memory, so this is fast
@@ -222,11 +224,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
222 { 224 {
223 region = m_GridService.GetRegionByPosition(scopeID, x, y); 225 region = m_GridService.GetRegionByPosition(scopeID, x, y);
224 if (region == null) 226 if (region == null)
227 {
225 m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>", 228 m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>",
226 LogHeader, x, y); 229 LogHeader, regionX, regionY);
230 }
227 else 231 else
232 {
228 m_log.DebugFormat("{0} GetRegionByPosition. Requested region {1} from grid service. Pos=<{2},{3}>", 233 m_log.DebugFormat("{0} GetRegionByPosition. Requested region {1} from grid service. Pos=<{2},{3}>",
229 LogHeader, region.RegionName, x, y); 234 LogHeader, region.RegionName, regionX, regionY);
235 }
230 } 236 }
231 return region; 237 return region;
232 } 238 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 6e1e8d6..c22c5b6 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -96,9 +96,88 @@ namespace OpenSim.Region.CoreModules.World.Terrain
96 private Scene m_scene; 96 private Scene m_scene;
97 private volatile bool m_tainted; 97 private volatile bool m_tainted;
98 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); 98 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5);
99 99
100 private String m_InitialTerrain = "pinhead-island"; 100 private String m_InitialTerrain = "pinhead-island";
101 101
102 // If true, send terrain patch updates to clients based on their view distance
103 private bool m_sendTerrainUpdatesByViewDistance = false;
104
105 // Class to keep the per client collection of terrain patches that must be sent.
106 // A patch is set to 'true' meaning it should be sent to the client. Once the
107 // patch packet is queued to the client, the bit for that patch is set to 'false'.
108 private class PatchUpdates
109 {
110 private bool[,] updated; // for each patch, whether it needs to be sent to this client
111 private int updateCount; // number of patches that need to be sent
112 public ScenePresence Presence; // a reference to the client to send to
113 public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
114 {
115 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
116 updateCount = 0;
117 Presence = pPresence;
118 // Initially, send all patches to the client
119 SetAll(true);
120 }
121 // Returns 'true' if there are any patches marked for sending
122 public bool HasUpdates()
123 {
124 return (updateCount > 0);
125 }
126 public void SetByXY(int x, int y, bool state)
127 {
128 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
129 }
130 public bool GetByPatch(int patchX, int patchY)
131 {
132 return updated[patchX, patchY];
133 }
134 public void SetByPatch(int patchX, int patchY, bool state)
135 {
136 bool prevState = updated[patchX, patchY];
137 if (!prevState && state)
138 updateCount++;
139 if (prevState && !state)
140 updateCount--;
141 updated[patchX, patchY] = state;
142 }
143 public void SetAll(bool state)
144 {
145 updateCount = 0;
146 for (int xx = 0; xx < updated.GetLength(0); xx++)
147 for (int yy = 0; yy < updated.GetLength(1); yy++)
148 updated[xx, yy] = state;
149 if (state)
150 updateCount = updated.GetLength(0) * updated.GetLength(1);
151 }
152 // Logically OR's the terrain data's patch taint map into this client's update map.
153 public void SetAll(TerrainData terrData)
154 {
155 if (updated.GetLength(0) != (terrData.SizeX / Constants.TerrainPatchSize)
156 || updated.GetLength(1) != (terrData.SizeY / Constants.TerrainPatchSize))
157 {
158 throw new Exception(
159 String.Format("{0} PatchUpdates.SetAll: patch array not same size as terrain. arr=<{1},{2}>, terr=<{3},{4}>",
160 LogHeader, updated.GetLength(0), updated.GetLength(1),
161 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
162 );
163 }
164 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
165 {
166 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
167 {
168 // Only set tainted. The patch bit may be set if the patch was to be sent later.
169 if (terrData.IsTaintedAt(xx, yy, false))
170 {
171 this.SetByXY(xx, yy, true);
172 }
173 }
174 }
175 }
176 }
177
178 // The flags of which terrain patches to send for each of the ScenePresence's
179 private Dictionary<UUID, PatchUpdates> m_perClientPatchUpdates = new Dictionary<UUID, PatchUpdates>();
180
102 /// <summary> 181 /// <summary>
103 /// Human readable list of terrain file extensions that are supported. 182 /// Human readable list of terrain file extensions that are supported.
104 /// </summary> 183 /// </summary>
@@ -127,7 +206,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
127 { 206 {
128 IConfig terrainConfig = config.Configs["Terrain"]; 207 IConfig terrainConfig = config.Configs["Terrain"];
129 if (terrainConfig != null) 208 if (terrainConfig != null)
209 {
130 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 210 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
211 m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance);
212 }
131 } 213 }
132 214
133 public void AddRegion(Scene scene) 215 public void AddRegion(Scene scene)
@@ -422,9 +504,46 @@ namespace OpenSim.Region.CoreModules.World.Terrain
422 } 504 }
423 } 505 }
424 506
507 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
508 // ITerrainModule.TaintTerrain()
425 public void TaintTerrain () 509 public void TaintTerrain ()
426 { 510 {
427 m_channel.GetTerrainData().TaintAllTerrain(); 511 lock (m_perClientPatchUpdates)
512 {
513 // Set the flags for all clients so the tainted patches will be sent out
514 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
515 {
516 pups.SetAll(m_scene.Heightmap.GetTerrainData());
517 }
518 }
519 }
520
521 // ITerrainModule.PushTerrain()
522 public void PushTerrain(IClientAPI pClient)
523 {
524 if (m_sendTerrainUpdatesByViewDistance)
525 {
526 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
527 if (presence != null)
528 {
529 lock (m_perClientPatchUpdates)
530 {
531 PatchUpdates pups;
532 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
533 {
534 // There is a ScenePresence without a send patch map. Create one.
535 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
536 m_perClientPatchUpdates.Add(presence.UUID, pups);
537 }
538 pups.SetAll(true);
539 }
540 }
541 }
542 else
543 {
544 // The traditional way is to call into the protocol stack to send them all.
545 pClient.SendLayerData(new float[10]);
546 }
428 } 547 }
429 548
430 #region Plugin Loading Methods 549 #region Plugin Loading Methods
@@ -676,6 +795,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
676 } 795 }
677 } 796 }
678 } 797 }
798
799 // This event also causes changes to be sent to the clients
800 CheckSendingPatchesToClients();
801
802 // If things changes, generate some events
679 if (shouldTaint) 803 if (shouldTaint)
680 { 804 {
681 m_scene.EventManager.TriggerTerrainTainted(); 805 m_scene.EventManager.TriggerTerrainTainted();
@@ -749,31 +873,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
749 presence.ControllingClient.OnLandUndo -= client_OnLandUndo; 873 presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
750 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 874 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
751 } 875 }
876 if (m_perClientPatchUpdates.ContainsKey(client))
877 {
878 m_perClientPatchUpdates.Remove(client);
879 }
752 } 880 }
753 881
754 /// <summary> 882 /// <summary>
755 /// Checks to see if the terrain has been modified since last check
756 /// but won't attempt to limit those changes to the limits specified in the estate settings
757 /// currently invoked by the command line operations in the region server only
758 /// </summary>
759 private void CheckForTerrainUpdates()
760 {
761 CheckForTerrainUpdates(false);
762 }
763
764 /// <summary>
765 /// Checks to see if the terrain has been modified since last check.
766 /// If it has been modified, every all the terrain patches are sent to the client.
767 /// If the call is asked to respect the estate settings for terrain_raise_limit and
768 /// terrain_lower_limit, it will clamp terrain updates between these values
769 /// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
770 /// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
771 /// </summary>
772 private void CheckForTerrainUpdates(bool respectEstateSettings)
773 {
774 }
775
776 /// <summary>
777 /// Scan over changes in the terrain and limit height changes. This enforces the 883 /// Scan over changes in the terrain and limit height changes. This enforces the
778 /// non-estate owner limits on rate of terrain editting. 884 /// non-estate owner limits on rate of terrain editting.
779 /// Returns 'true' if any heights were limited. 885 /// Returns 'true' if any heights were limited.
@@ -857,17 +963,140 @@ namespace OpenSim.Region.CoreModules.World.Terrain
857 /// <param name="y">The patch corner to send</param> 963 /// <param name="y">The patch corner to send</param>
858 private void SendToClients(TerrainData terrData, int x, int y) 964 private void SendToClients(TerrainData terrData, int x, int y)
859 { 965 {
860 // We know the actual terrain data passed is ignored. This kludge saves changing IClientAPI. 966 if (m_sendTerrainUpdatesByViewDistance)
861 //float[] heightMap = terrData.GetFloatsSerialized(); 967 {
862 float[] heightMap = new float[10]; 968 // Add that this patch needs to be sent to the accounting for each client.
863 m_scene.ForEachClient( 969 lock (m_perClientPatchUpdates)
864 delegate(IClientAPI controller) 970 {
971 m_scene.ForEachScenePresence(presence =>
972 {
973 PatchUpdates thisClientUpdates;
974 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
975 {
976 // There is a ScenePresence without a send patch map. Create one.
977 thisClientUpdates = new PatchUpdates(terrData, presence);
978 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
979 }
980 thisClientUpdates.SetByXY(x, y, true);
981 }
982 );
983 }
984 }
985 else
986 {
987 // Legacy update sending where the update is sent out as soon as noticed
988 // We know the actual terrain data passed is ignored. This kludge saves changing IClientAPI.
989 //float[] heightMap = terrData.GetFloatsSerialized();
990 float[] heightMap = new float[10];
991 m_scene.ForEachClient(
992 delegate(IClientAPI controller)
865 { 993 {
866 controller.SendLayerData( x / Constants.TerrainPatchSize, 994 controller.SendLayerData(x / Constants.TerrainPatchSize,
867 y / Constants.TerrainPatchSize, 995 y / Constants.TerrainPatchSize,
868 heightMap); 996 heightMap);
869 } 997 }
870 ); 998 );
999 }
1000 }
1001
1002 private class PatchesToSend : IComparable<PatchesToSend>
1003 {
1004 public int PatchX;
1005 public int PatchY;
1006 public float Dist;
1007 public PatchesToSend(int pX, int pY, float pDist)
1008 {
1009 PatchX = pX;
1010 PatchY = pY;
1011 Dist = pDist;
1012 }
1013 public int CompareTo(PatchesToSend other)
1014 {
1015 return Dist.CompareTo(other.Dist);
1016 }
1017 }
1018
1019 // Called each frame time to see if there are any patches to send to any of the
1020 // ScenePresences.
1021 // Loop through all the per-client info and send any patches necessary.
1022 private void CheckSendingPatchesToClients()
1023 {
1024 lock (m_perClientPatchUpdates)
1025 {
1026 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
1027 {
1028 if (pups.HasUpdates())
1029 {
1030 // There is something that could be sent to this client.
1031 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1032 if (toSend.Count > 0)
1033 {
1034 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
1035 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
1036 // Sort the patches to send by the distance from the presence
1037 toSend.Sort();
1038 foreach (PatchesToSend pts in toSend)
1039 {
1040 // TODO: one can send multiple patches in a packet. Do that.
1041 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1042 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1043 }
1044 }
1045 }
1046 }
1047 }
1048 }
1049
1050 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
1051 {
1052 List<PatchesToSend> ret = new List<PatchesToSend>();
1053
1054 ScenePresence presence = pups.Presence;
1055 if (presence == null)
1056 return ret;
1057
1058 // Compute the area of patches within our draw distance
1059 int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
1060 startX = Math.Max(startX, 0);
1061 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
1062 int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2;
1063 startY = Math.Max(startY, 0);
1064 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
1065 int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
1066 endX = Math.Max(endX, 0);
1067 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize);
1068 int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2;
1069 endY = Math.Max(endY, 0);
1070 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize);
1071 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
1072 // LogHeader, m_scene.RegionInfo.RegionName,
1073 // presence.DrawDistance, presence.AbsolutePosition,
1074 // startX, startY, endX, endY);
1075 for (int x = startX; x < endX; x++)
1076 {
1077 for (int y = startY; y < endY; y++)
1078 {
1079 //Need to make sure we don't send the same ones over and over
1080 Vector3 presencePos = presence.AbsolutePosition;
1081 Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
1082 if (pups.GetByPatch(x, y))
1083 {
1084 //Check which has less distance, camera or avatar position, both have to be done.
1085 //Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off
1086 if (Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50)
1087 || Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
1088 {
1089 //They can see it, send it to them
1090 pups.SetByPatch(x, y, false);
1091 float dist = Vector3.DistanceSquared(presencePos, patchPos);
1092 ret.Add(new PatchesToSend(x, y, dist));
1093 //Wait and send them all at once
1094 // pups.client.SendLayerData(x, y, null);
1095 }
1096 }
1097 }
1098 }
1099 return ret;
871 } 1100 }
872 1101
873 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action, 1102 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
index a6f5d98..28f797a 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
@@ -24,9 +24,10 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System.IO;
27 28
29using OpenSim.Framework;
28 30
29using System.IO;
30using OpenMetaverse; 31using OpenMetaverse;
31 32
32namespace OpenSim.Region.Framework.Interfaces 33namespace OpenSim.Region.Framework.Interfaces
@@ -44,6 +45,12 @@ namespace OpenSim.Region.Framework.Interfaces
44 void TaintTerrain(); 45 void TaintTerrain();
45 46
46 /// <summary> 47 /// <summary>
48 /// When a client initially connects, all the terrain must be pushed to the viewer.
49 /// This call causes all the terrain patches to be sent to the client.
50 /// </summary>
51 void PushTerrain(IClientAPI pClient);
52
53 /// <summary>
47 /// Load a terrain from a stream. 54 /// Load a terrain from a stream.
48 /// </summary> 55 /// </summary>
49 /// <param name="filename"> 56 /// <param name="filename">
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 4208669..0445268 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -213,7 +213,12 @@ namespace OpenSim.Region.Framework.Scenes
213 /// <param name="RemoteClient">Client to send to</param> 213 /// <param name="RemoteClient">Client to send to</param>
214 public virtual void SendLayerData(IClientAPI RemoteClient) 214 public virtual void SendLayerData(IClientAPI RemoteClient)
215 { 215 {
216 RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised()); 216 // RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised());
217 ITerrainModule terrModule = RequestModuleInterface<ITerrainModule>();
218 if (terrModule != null)
219 {
220 terrModule.PushTerrain(RemoteClient);
221 }
217 } 222 }
218 223
219 #endregion 224 #endregion
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index c873e40..45c3348 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes
52 public class SceneCommunicationService //one instance per region 52 public class SceneCommunicationService //one instance per region
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static string LogHeader = "[SCENE COMMUNIATION SERVICE]";
55 56
56 protected RegionInfo m_regionInfo; 57 protected RegionInfo m_regionInfo;
57 protected Scene m_scene; 58 protected Scene m_scene;
@@ -84,15 +85,12 @@ namespace OpenSim.Region.Framework.Scenes
84 if (neighbourService != null) 85 if (neighbourService != null)
85 neighbour = neighbourService.HelloNeighbour(regionhandle, region); 86 neighbour = neighbourService.HelloNeighbour(regionhandle, region);
86 else 87 else
87 m_log.DebugFormat( 88 m_log.DebugFormat( "{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name);
88 "[SCENE COMMUNICATION SERVICE]: No neighbour service provided for region {0} to inform neigbhours of status",
89 m_scene.Name);
90 89
91 if (neighbour != null) 90 if (neighbour != null)
92 { 91 {
93 m_log.DebugFormat( 92 m_log.DebugFormat( "{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up",
94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up", 93 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
95 m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
96 94
97 m_scene.EventManager.TriggerOnRegionUp(neighbour); 95 m_scene.EventManager.TriggerOnRegionUp(neighbour);
98 } 96 }
@@ -111,9 +109,7 @@ namespace OpenSim.Region.Framework.Scenes
111 List<GridRegion> neighbours 109 List<GridRegion> neighbours
112 = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 110 = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
113 111
114 m_log.DebugFormat( 112 m_log.DebugFormat("{0} Informing {1} neighbours that region {2} is up", LogHeader, neighbours.Count, m_scene.Name);
115 "[SCENE COMMUNICATION SERVICE]: Informing {0} neighbours that region {1} is up",
116 neighbours.Count, m_scene.Name);
117 113
118 foreach (GridRegion n in neighbours) 114 foreach (GridRegion n in neighbours)
119 { 115 {
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 37353c1..063ac73 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -873,7 +873,8 @@ namespace OpenSim.Region.Framework.Scenes
873 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 873 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
874 Animator = new ScenePresenceAnimator(this); 874 Animator = new ScenePresenceAnimator(this);
875 PresenceType = type; 875 PresenceType = type;
876 DrawDistance = world.DefaultDrawDistance; 876 // DrawDistance = world.DefaultDrawDistance;
877 DrawDistance = Constants.RegionSize;
877 RegionHandle = world.RegionInfo.RegionHandle; 878 RegionHandle = world.RegionInfo.RegionHandle;
878 ControllingClient = client; 879 ControllingClient = client;
879 Firstname = ControllingClient.FirstName; 880 Firstname = ControllingClient.FirstName;
@@ -1918,8 +1919,8 @@ namespace OpenSim.Region.Framework.Scenes
1918 // When we get to the point of re-computing neighbors everytime this 1919 // When we get to the point of re-computing neighbors everytime this
1919 // changes, then start using the agent's drawdistance rather than the 1920 // changes, then start using the agent's drawdistance rather than the
1920 // region's draw distance. 1921 // region's draw distance.
1921 // DrawDistance = agentData.Far; 1922 DrawDistance = agentData.Far;
1922 DrawDistance = Scene.DefaultDrawDistance; 1923 // DrawDistance = Scene.DefaultDrawDistance;
1923 1924
1924 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 1925 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1925 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; 1926 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
@@ -2277,8 +2278,8 @@ namespace OpenSim.Region.Framework.Scenes
2277 // When we get to the point of re-computing neighbors everytime this 2278 // When we get to the point of re-computing neighbors everytime this
2278 // changes, then start using the agent's drawdistance rather than the 2279 // changes, then start using the agent's drawdistance rather than the
2279 // region's draw distance. 2280 // region's draw distance.
2280 // DrawDistance = agentData.Far; 2281 DrawDistance = agentData.Far;
2281 DrawDistance = Scene.DefaultDrawDistance; 2282 // DrawDistance = Scene.DefaultDrawDistance;
2282 2283
2283 // Check if Client has camera in 'follow cam' or 'build' mode. 2284 // Check if Client has camera in 'follow cam' or 'build' mode.
2284 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); 2285 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
@@ -3824,8 +3825,8 @@ namespace OpenSim.Region.Framework.Scenes
3824 // When we get to the point of re-computing neighbors everytime this 3825 // When we get to the point of re-computing neighbors everytime this
3825 // changes, then start using the agent's drawdistance rather than the 3826 // changes, then start using the agent's drawdistance rather than the
3826 // region's draw distance. 3827 // region's draw distance.
3827 // DrawDistance = cAgentData.Far; 3828 DrawDistance = cAgentData.Far;
3828 DrawDistance = Scene.DefaultDrawDistance; 3829 // DrawDistance = Scene.DefaultDrawDistance;
3829 3830
3830 if (cAgentData.Position != marker) // UGH!! 3831 if (cAgentData.Position != marker) // UGH!!
3831 m_pos = cAgentData.Position + offset; 3832 m_pos = cAgentData.Position + offset;
@@ -3935,8 +3936,8 @@ namespace OpenSim.Region.Framework.Scenes
3935 // When we get to the point of re-computing neighbors everytime this 3936 // When we get to the point of re-computing neighbors everytime this
3936 // changes, then start using the agent's drawdistance rather than the 3937 // changes, then start using the agent's drawdistance rather than the
3937 // region's draw distance. 3938 // region's draw distance.
3938 // DrawDistance = cAgent.Far; 3939 DrawDistance = cAgent.Far;
3939 DrawDistance = Scene.DefaultDrawDistance; 3940 // DrawDistance = Scene.DefaultDrawDistance;
3940 3941
3941 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 3942 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
3942 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 3943 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index 8198592..36957a7 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -46,6 +46,7 @@ namespace OpenSim.Services.GridService
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger( 47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
49 private string LogHeader = "[GRID SERVICE]";
49 50
50 private bool m_DeleteOnUnregister = true; 51 private bool m_DeleteOnUnregister = true;
51 private static GridService m_RootInstance = null; 52 private static GridService m_RootInstance = null;
@@ -328,7 +329,11 @@ namespace OpenSim.Services.GridService
328 } 329 }
329 } 330 }
330 331
331// m_log.DebugFormat("[GRID SERVICE]: region {0} has {1} neighbours", region.RegionName, rinfos.Count); 332 // string rNames = "";
333 // foreach (GridRegion gr in rinfos)
334 // rNames += gr.RegionName + ",";
335 // m_log.DebugFormat("{0} region {1} has {2} neighbours ({3})",
336 // LogHeader, region.RegionName, rinfos.Count, rNames);
332 } 337 }
333 else 338 else
334 { 339 {
@@ -657,7 +662,7 @@ namespace OpenSim.Services.GridService
657 return; 662 return;
658 } 663 }
659 664
660 RegionData region = m_Database.Get((int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y), UUID.Zero); 665 RegionData region = m_Database.Get((int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y), UUID.Zero);
661 if (region == null) 666 if (region == null)
662 { 667 {
663 MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y); 668 MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y);
diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs
index 31e147b..0e425f8 100644
--- a/OpenSim/Services/MapImageService/MapImageService.cs
+++ b/OpenSim/Services/MapImageService/MapImageService.cs
@@ -36,6 +36,7 @@ using System.Drawing.Imaging;
36using System.IO; 36using System.IO;
37using System.Net; 37using System.Net;
38using System.Reflection; 38using System.Reflection;
39using System.Threading;
39 40
40using Nini.Config; 41using Nini.Config;
41using log4net; 42using log4net;
@@ -53,6 +54,7 @@ namespace OpenSim.Services.MapImageService
53 private static readonly ILog m_log = 54 private static readonly ILog m_log =
54 LogManager.GetLogger( 55 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType); 56 MethodBase.GetCurrentMethod().DeclaringType);
57 private string LogHeader = "[MAP IMAGE SERVICE]";
56 58
57 private const int ZOOM_LEVELS = 8; 59 private const int ZOOM_LEVELS = 8;
58 private const int IMAGE_WIDTH = 256; 60 private const int IMAGE_WIDTH = 256;
@@ -114,7 +116,7 @@ namespace OpenSim.Services.MapImageService
114 } 116 }
115 } 117 }
116 118
117 return UpdateMultiResolutionFiles(x, y, out reason); 119 return UpdateMultiResolutionFilesAsync(x, y, out reason);
118 } 120 }
119 121
120 public bool RemoveMapTile(int x, int y, out string reason) 122 public bool RemoveMapTile(int x, int y, out string reason)
@@ -136,33 +138,81 @@ namespace OpenSim.Services.MapImageService
136 } 138 }
137 } 139 }
138 140
139 return UpdateMultiResolutionFiles(x, y, out reason); 141 return UpdateMultiResolutionFilesAsync(x, y, out reason);
140 } 142 }
141 143
142 private bool UpdateMultiResolutionFiles(int x, int y, out string reason) 144 // When large varregions start up, they can send piles of new map tiles. This causes
145 // this multi-resolution routine to be called a zillion times an causes much CPU
146 // time to be spent creating multi-resolution tiles that will be replaced when
147 // the next maptile arrives.
148 private class mapToMultiRez
149 {
150 public int xx;
151 public int yy;
152 public mapToMultiRez(int pX, int pY)
153 {
154 xx = pX;
155 yy = pY;
156 }
157 };
158 private Queue<mapToMultiRez> multiRezToBuild = new Queue<mapToMultiRez>();
159 private bool UpdateMultiResolutionFilesAsync(int x, int y, out string reason)
143 { 160 {
144 reason = String.Empty; 161 reason = String.Empty;
145 lock (m_Sync) 162 lock (multiRezToBuild)
146 { 163 {
147 // Stitch seven more aggregate tiles together 164 // m_log.DebugFormat("{0} UpdateMultiResolutionFilesAsync: scheduling update for <{1},{2}>", LogHeader, x, y);
148 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) 165 multiRezToBuild.Enqueue(new mapToMultiRez(x, y));
166 if (multiRezToBuild.Count == 1)
167 Util.FireAndForget(DoUpdateMultiResolutionFilesAsync);
168 }
169
170 return true;
171 }
172
173 private void DoUpdateMultiResolutionFilesAsync(object o)
174 {
175 // This sleep causes the FireAndForget thread to be different than the invocation thread.
176 // It also allows other tiles to be uploaded so the multi-rez images are more likely
177 // to be correct.
178 Thread.Sleep(1 * 1000);
179
180 while (multiRezToBuild.Count > 0)
181 {
182 mapToMultiRez toMultiRez = null;
183 lock (multiRezToBuild)
149 { 184 {
150 // Calculate the width (in full resolution tiles) and bottom-left 185 if (multiRezToBuild.Count > 0)
151 // corner of the current zoom level 186 toMultiRez = multiRezToBuild.Dequeue();
152 int width = (int)Math.Pow(2, (double)(zoomLevel - 1)); 187 }
153 int x1 = x - (x % width); 188 if (toMultiRez != null)
154 int y1 = y - (y % width); 189 {
190 int x = toMultiRez.xx;
191 int y = toMultiRez.yy;
192 // m_log.DebugFormat("{0} DoUpdateMultiResolutionFilesAsync: doing build for <{1},{2}>", LogHeader, x, y);
155 193
156 if (!CreateTile(zoomLevel, x1, y1)) 194 // Stitch seven more aggregate tiles together
195 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
157 { 196 {
158 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel); 197 // Calculate the width (in full resolution tiles) and bottom-left
159 reason = string.Format("Map tile at zoom level {0} failed", zoomLevel); 198 // corner of the current zoom level
160 return false; 199 int width = (int)Math.Pow(2, (double)(zoomLevel - 1));
200 int x1 = x - (x % width);
201 int y1 = y - (y % width);
202
203 lock (m_Sync) // must lock the reading and writing of the maptile files
204 {
205 if (!CreateTile(zoomLevel, x1, y1))
206 {
207 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel);
208 return;
209 }
210 }
161 } 211 }
162 } 212 }
163 } 213 }
164 214
165 return true; 215 return;
166 } 216 }
167 217
168 public byte[] GetMapTile(string fileName, out string format) 218 public byte[] GetMapTile(string fileName, out string format)