diff options
author | Diva Canto | 2014-06-01 10:06:59 -0700 |
---|---|---|
committer | Diva Canto | 2014-06-01 10:06:59 -0700 |
commit | 0eaca7aafb0365fb21b6d1ce8e1590845a6b5125 (patch) | |
tree | 1120139228e2c934de544f3288b306699018bb50 /OpenSim/Region/CoreModules | |
parent | Fixed a few things pertaining to interfacing with the estate service. Specifi... (diff) | |
parent | Move the generation of the multi-resolution map tiles off the main (diff) | |
download | opensim-SC-0eaca7aafb0365fb21b6d1ce8e1590845a6b5125.zip opensim-SC-0eaca7aafb0365fb21b6d1ce8e1590845a6b5125.tar.gz opensim-SC-0eaca7aafb0365fb21b6d1ce8e1590845a6b5125.tar.bz2 opensim-SC-0eaca7aafb0365fb21b6d1ce8e1590845a6b5125.tar.xz |
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim/Region/CoreModules')
3 files changed, 277 insertions, 41 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, |