diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5f8d8f1ab8..90f0336869 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1390,11 +1390,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Send the cloud matrix to the client /// /// 16x16 array of cloud densities +/* public virtual void SendCloudData(int version, float[] cloudDensity) { Util.FireAndForget(DoSendCloudData, cloudDensity, "LLClientView.SendCloudData"); } - +*/ // wind caching private static int lastWindVersion = 0; private static List lastWindPackets = new List(); @@ -1445,30 +1446,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(pkt, ThrottleOutPacketType.Wind); } + // cloud caching + private static int lastCloudVersion = 0; + private static List lastCloudPackets = new List(); + /// /// Send cloud layer information to the client. /// /// - private void DoSendCloudData(object o) +// private void DoSendCloudData(object o) + public virtual void SendCloudData(int version, float[] cloudDensity) { - float[] cloudCover = (float[])o; - TerrainPatch[] patches = new TerrainPatch[1]; - patches[0] = new TerrainPatch(); - patches[0].Data = new float[16 * 16]; +// float[] cloudDensity = (float[])o; + bool isNewData; + lock(lastCloudPackets) + isNewData = lastCloudVersion != version; - for (int y = 0; y < 16; y++) + if(isNewData) { - for (int x = 0; x < 16; x++) + TerrainPatch[] patches = new TerrainPatch[1]; + patches[0] = new TerrainPatch(); + patches[0].Data = new float[16 * 16]; + + for (int y = 0; y < 16; y++) { - patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x]; + for (int x = 0; x < 16; x++) + { + patches[0].Data[y * 16 + x] = cloudDensity[y * 16 + x]; + } + } + // neither we or viewers have extended clouds + byte layerType = (byte)TerrainPatch.LayerType.Cloud; + + LayerDataPacket layerpack = + OpenSimTerrainCompressor.CreateLayerDataPacketStandardSize( + patches, layerType); + layerpack.Header.Zerocoded = true; + lock(lastCloudPackets) + { + lastCloudPackets.Clear(); + lastCloudPackets.Add(layerpack); + lastCloudVersion = version; } } - // neither we or viewers have extended clouds - byte layerType = (byte)TerrainPatch.LayerType.Cloud; - LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacketStandardSize(patches, layerType); - layerpack.Header.Zerocoded = true; - OutPacket(layerpack, ThrottleOutPacketType.Cloud); + lock(lastCloudPackets) + foreach(LayerDataPacket pkt in lastCloudPackets) + OutPacket(pkt, ThrottleOutPacketType.Cloud); } /// diff --git a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs index f304307586..3c2884b385 100644 --- a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs +++ b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Threading; using Mono.Addins; using Nini.Config; using OpenMetaverse; @@ -49,6 +50,10 @@ namespace OpenSim.Region.CoreModules.World private bool m_enabled = false; private float m_cloudDensity = 1.0F; private float[] cloudCover = new float[16 * 16]; + private int m_dataVersion; + private bool m_busy; + private object cloudlock = new object(); + public void Initialise(IConfigSource config) { @@ -70,11 +75,13 @@ namespace OpenSim.Region.CoreModules.World m_scene = scene; - scene.EventManager.OnNewClient += CloudsToClient; scene.RegisterModuleInterface(this); - scene.EventManager.OnFrame += CloudUpdate; GenerateCloudCover(); + m_dataVersion = (int)m_scene.AllocateLocalId(); + + scene.EventManager.OnNewClient += CloudsToClient; + scene.EventManager.OnFrame += CloudUpdate; m_ready = true; } @@ -89,7 +96,6 @@ namespace OpenSim.Region.CoreModules.World m_scene.EventManager.OnNewClient -= CloudsToClient; m_scene.EventManager.OnFrame -= CloudUpdate; m_scene.UnregisterModuleInterface(this); - m_scene = null; } @@ -127,7 +133,8 @@ namespace OpenSim.Region.CoreModules.World if (cloudCover != null) { - cover = cloudCover[y * 16 + x]; + lock(cloudlock) + cover = cloudCover[y * 16 + x]; } return cover; @@ -188,22 +195,48 @@ namespace OpenSim.Region.CoreModules.World } } Array.Copy(newCover, cloudCover, 16 * 16); + m_dataVersion++; } - private void CloudUpdate() - { - if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready || (m_cloudDensity == 0)) - { - return; - } - UpdateCloudCover(); + private void CloudUpdate() + { + if ((!m_ready || m_cloudDensity == 0 || (m_frame++ % m_frameUpdateRate) != 0)) + { + return; + } + + if(Monitor.TryEnter(cloudlock)) + { + m_busy = true; + Util.FireAndForget(delegate + { + try + { + lock(cloudlock) + { + UpdateCloudCover(); + m_scene.ForEachClient(delegate(IClientAPI client) + { + client.SendCloudData(m_dataVersion, cloudCover); + }); + } + } + finally + { + m_busy = false; + } + }, + null, "CloudModuleUpdate"); + Monitor.Exit(cloudlock); + } } public void CloudsToClient(IClientAPI client) { if (m_ready) { - client.SendCloudData(0, cloudCover); + lock(cloudlock) + client.SendCloudData(m_dataVersion, cloudCover); } } diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs index bc92582c30..95cf57d20d 100644 --- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs +++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs @@ -425,7 +425,7 @@ namespace OpenSim.Region.CoreModules try { GenWind(); - m_scene.ForEachRootClient(delegate(IClientAPI client) + m_scene.ForEachClient(delegate(IClientAPI client) { client.SendWindData(m_dataVersion, windSpeeds); });