From e5d10bf12789c35b1f77ad1f31211417ee22ea62 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 29 Mar 2025 01:21:43 +0000 Subject: [PATCH] try to fix some terrain issues, Add some more locking --- OpenSim/Framework/TerrainData.cs | 3 +- .../World/Terrain/TerrainModule.cs | 293 +++++++++--------- 2 files changed, 155 insertions(+), 141 deletions(-) diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index bbaebb838c..da6fc3f242 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs @@ -364,7 +364,6 @@ namespace OpenSim.Framework zmax = float.MinValue; zmin = float.MaxValue; - int mpy = Constants.TerrainPatchSize * py; fixed (float* map = m_heightmap) { @@ -379,7 +378,7 @@ namespace OpenSim.Framework float val = *yt; if (val > zmax) zmax = val; - else if (val < zmin) + if (val < zmin) zmin = val; yt++; } diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index c0d092a82b..02fdca6a08 100755 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -72,6 +72,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private object _modifyLock = new(); + #pragma warning disable 414 private static readonly string LogHeader = "[TERRAIN MODULE]"; #pragma warning restore 414 @@ -876,7 +878,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// doing it async, since currently this is 2 heavy for heartbeat private void EventManager_TerrainCheckUpdates() { - Util.FireAndForget(EventManager_TerrainCheckUpdatesAsync); + if(Monitor.TryEnter(_modifyLock)) + { + Util.FireAndForget(EventManager_TerrainCheckUpdatesAsync); + Monitor.Exit(_modifyLock); + } } object TerrainCheckUpdatesLock = new object(); @@ -919,14 +925,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// private void EventManager_OnTerrainTick() { - if (m_tainted) - { - m_tainted = false; - m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); - m_scene.SaveTerrain(); + if(Monitor.TryEnter(_modifyLock)) + { + { + if (m_tainted) + { + m_tainted = false; + m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); + m_scene.SaveTerrain(); - // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. - //m_scene.CreateTerrainTexture(true); + // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. + //m_scene.CreateTerrainTexture(true); + } + } + Monitor.Exit(_modifyLock); } } @@ -1009,14 +1021,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain return wasLimited; } - private bool EnforceEstateLimits(int startX, int startY, int endX, int endY) + private bool EnforceEstateLimits(int startX, int endX, int startY, int endY) { TerrainData terrData = m_channel.GetTerrainData(); bool wasLimited = false; for (int x = startX; x <= endX; x += Constants.TerrainPatchSize) { - for (int y = startX; y <= endY; y += Constants.TerrainPatchSize) + for (int y = startY; y <= endY; y += Constants.TerrainPatchSize) { if (terrData.IsTaintedAt(x, y)) { @@ -1322,163 +1334,166 @@ namespace OpenSim.Region.CoreModules.World.Terrain double now = Util.GetTimeStamp(); if(now < NextModifyTerrainTime) return; - - try - { - NextModifyTerrainTime = double.MaxValue; // block it - - //m_log.DebugFormat("brushs {0} seconds {1} height {2}, parcel {3}", brushSize, seconds, height, parcelLocalID); - bool god = m_scene.Permissions.IsGod(user); - bool allowed = false; - if (north == south && east == west) + if(Monitor.TryEnter(_modifyLock)) + { + try { - if (m_painteffects.ContainsKey((StandardTerrainEffects)action)) + NextModifyTerrainTime = double.MaxValue; // block it + + //m_log.DebugFormat("brushs {0} seconds {1} height {2}, parcel {3}", brushSize, seconds, height, parcelLocalID); + bool god = m_scene.Permissions.IsGod(user); + bool allowed = false; + if (north == south && east == west) { - bool[,] allowMask = new bool[m_channel.Width, m_channel.Height]; - - allowMask.Initialize(); - - int startX = (int)(west - brushSize + 0.5); - if (startX < 0) - startX = 0; - - int startY = (int)(north - brushSize + 0.5); - if (startY < 0) - startY = 0; - - int endX = (int)(west + brushSize + 0.5); - if (endX >= m_channel.Width) - endX = m_channel.Width - 1; - int endY = (int)(north + brushSize + 0.5); - if (endY >= m_channel.Height) - endY = m_channel.Height - 1; - - int x, y; - - for (x = startX; x <= endX; x++) + if (m_painteffects.ContainsKey((StandardTerrainEffects)action)) { - for (y = startY; y <= endY; y++) - { - if (m_scene.Permissions.CanTerraformLand(user, new Vector3(x, y, -1))) - { - allowMask[x, y] = true; - allowed = true; - } - } - } - if (allowed) - { - StoreUndoState(); - m_painteffects[(StandardTerrainEffects) action].PaintEffect( - m_channel, allowMask, west, south, height, brushSize, seconds, - startX, endX, startY, endY); + bool[,] allowMask = new bool[m_channel.Width, m_channel.Height]; - //block changes outside estate limits - if (!god) - EnforceEstateLimits(startX, endX, startY, endY); - } - } - else - { - m_log.Debug("Unknown terrain brush type " + action); - } - } - else - { - if (m_floodeffects.ContainsKey((StandardTerrainEffects)action)) - { - bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; - fillArea.Initialize(); + allowMask.Initialize(); - int startX = (int)west; - int startY = (int)south; - int endX = (int)east; - int endY = (int)north; + int startX = (int)(west - brushSize + 0.5); + if (startX < 0) + startX = 0; - if (startX < 0) - startX = 0; - else if (startX >= m_channel.Width) - startX = m_channel.Width - 1; + int startY = (int)(north - brushSize + 0.5); + if (startY < 0) + startY = 0; - if (endX < 0) - endX = 0; - else if (endX >= m_channel.Width) - endX = m_channel.Width - 1; + int endX = (int)(west + brushSize + 0.5); + if (endX >= m_channel.Width) + endX = m_channel.Width - 1; + int endY = (int)(north + brushSize + 0.5); + if (endY >= m_channel.Height) + endY = m_channel.Height - 1; - if (startY < 0) - startY = 0; - else if (startY >= m_channel.Height) - startY = m_channel.Height - 1; + int x, y; - if (endY < 0) - endY = 0; - else if (endY >= m_channel.Height) - endY = m_channel.Height - 1; - - int x, y; - if (parcelLocalID == -1) - { for (x = startX; x <= endX; x++) { for (y = startY; y <= endY; y++) { if (m_scene.Permissions.CanTerraformLand(user, new Vector3(x, y, -1))) { - fillArea[x, y] = true; + allowMask[x, y] = true; allowed = true; } } } + if (allowed) + { + StoreUndoState(); + m_painteffects[(StandardTerrainEffects) action].PaintEffect( + m_channel, allowMask, west, south, height, brushSize, seconds, + startX, endX, startY, endY); + + //block changes outside estate limits + if (!god) + EnforceEstateLimits(startX, endX, startY, endY); + } } else { - if (!m_scene.Permissions.CanTerraformLand(user, new Vector3(-1, -1, parcelLocalID))) - return; - - ILandObject parcel = m_scene.LandChannel.GetLandObject(parcelLocalID); - if(parcel == null) - return; - - bool[,] parcelmap = parcel.GetLandBitmap(); - //ugly - for (x = startX; x <= endX; x++) - { - int px = x >> 2; - y = startY; - while( y <= endY) - { - int py = y >> 2; - bool inp = parcelmap[px, py]; - fillArea[x, y++] = inp; - fillArea[x, y++] = inp; - fillArea[x, y++] = inp; - fillArea[x, y++] = inp; - } - } - - allowed = true; - } - - if (allowed) - { - StoreUndoState(); - m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, height, seconds, - startX, endX, startY, endY); - - //block changes outside estate limits - if (!god) - EnforceEstateLimits(startX, endX, startY, endY); + m_log.Debug("Unknown terrain brush type " + action); } } else { - m_log.Debug("Unknown terrain flood type " + action); + if (m_floodeffects.ContainsKey((StandardTerrainEffects)action)) + { + bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; + fillArea.Initialize(); + + int startX = (int)west; + int startY = (int)south; + int endX = (int)east; + int endY = (int)north; + + if (startX < 0) + startX = 0; + else if (startX >= m_channel.Width) + startX = m_channel.Width - 1; + + if (endX < 0) + endX = 0; + else if (endX >= m_channel.Width) + endX = m_channel.Width - 1; + + if (startY < 0) + startY = 0; + else if (startY >= m_channel.Height) + startY = m_channel.Height - 1; + + if (endY < 0) + endY = 0; + else if (endY >= m_channel.Height) + endY = m_channel.Height - 1; + + int x, y; + if (parcelLocalID == -1) + { + for (x = startX; x <= endX; x++) + { + for (y = startY; y <= endY; y++) + { + if (m_scene.Permissions.CanTerraformLand(user, new Vector3(x, y, -1))) + { + fillArea[x, y] = true; + allowed = true; + } + } + } + } + else + { + if (!m_scene.Permissions.CanTerraformLand(user, new Vector3(-1, -1, parcelLocalID))) + return; + + ILandObject parcel = m_scene.LandChannel.GetLandObject(parcelLocalID); + if(parcel == null) + return; + + bool[,] parcelmap = parcel.GetLandBitmap(); + //ugly + for (x = startX; x <= endX; x++) + { + int px = x >> 2; + y = startY; + while( y <= endY) + { + int py = y >> 2; + bool inp = parcelmap[px, py]; + fillArea[x, y++] = inp; + fillArea[x, y++] = inp; + fillArea[x, y++] = inp; + fillArea[x, y++] = inp; + } + } + + allowed = true; + } + + if (allowed) + { + StoreUndoState(); + m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, height, seconds, + startX, endX, startY, endY); + + //block changes outside estate limits + if (!god) + EnforceEstateLimits(startX, endX, startY, endY); + } + } + else + { + m_log.Debug("Unknown terrain flood type " + action); + } } } - } - finally - { - NextModifyTerrainTime = Util.GetTimeStamp() + 0.02; // 20ms cooldown + finally + { + NextModifyTerrainTime = Util.GetTimeStamp() + 0.02; // 20ms cooldown + } + Monitor.Exit(_modifyLock); } }