aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
diff options
context:
space:
mode:
authorDev Random2015-05-06 13:15:41 -0400
committerMichael Cerquoni2015-05-06 13:55:22 -0400
commit4bf62e11b6a99c024e3dfa42db7425ea790009ee (patch)
treeff845c62f5e354ddeb60ec02edba112ff2b5b227 /OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
parentAttempt at fixing mantis #7054. The two inventory threads are stepping on eac... (diff)
downloadopensim-SC_OLD-4bf62e11b6a99c024e3dfa42db7425ea790009ee.zip
opensim-SC_OLD-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.gz
opensim-SC_OLD-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.bz2
opensim-SC_OLD-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.xz
'terrain modify' command for area-of-effect operations
Signed-off-by: Michael Cerquoni <nebadon2025@gmail.com>
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs339
1 files changed, 196 insertions, 143 deletions
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 3bb8040..02f21b9 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -24,7 +24,6 @@
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 */
27
28using System; 27using System;
29using System.Collections.Generic; 28using System.Collections.Generic;
30using System.IO; 29using System.IO;
@@ -43,6 +42,7 @@ using OpenSim.Framework.Console;
43using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 42using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
44using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; 43using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
45using OpenSim.Region.CoreModules.World.Terrain.Features; 44using OpenSim.Region.CoreModules.World.Terrain.Features;
45using OpenSim.Region.CoreModules.World.Terrain.Modifiers;
46using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; 46using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes;
47using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; 47using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
48using OpenSim.Region.Framework.Interfaces; 48using OpenSim.Region.Framework.Interfaces;
@@ -90,26 +90,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain
90#pragma warning restore 414 90#pragma warning restore 414
91 91
92 private readonly Commander m_commander = new Commander("terrain"); 92 private readonly Commander m_commander = new Commander("terrain");
93
94 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects = 93 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
95 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>(); 94 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
96
97 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); 95 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
98
99 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 96 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
100 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 97 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
101
102 private Dictionary<string, ITerrainEffect> m_plugineffects; 98 private Dictionary<string, ITerrainEffect> m_plugineffects;
103
104 private Dictionary<string, ITerrainFeature> m_featureEffects = 99 private Dictionary<string, ITerrainFeature> m_featureEffects =
105 new Dictionary<string, ITerrainFeature>(); 100 new Dictionary<string, ITerrainFeature>();
106 101 private Dictionary<string, ITerrainModifier> m_modifyOperations =
102 new Dictionary<string, ITerrainModifier>();
107 private ITerrainChannel m_channel; 103 private ITerrainChannel m_channel;
108 private ITerrainChannel m_revert; 104 private ITerrainChannel m_revert;
109 private Scene m_scene; 105 private Scene m_scene;
110 private volatile bool m_tainted; 106 private volatile bool m_tainted;
111 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); 107 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5);
112
113 private String m_InitialTerrain = "pinhead-island"; 108 private String m_InitialTerrain = "pinhead-island";
114 109
115 // If true, send terrain patch updates to clients based on their view distance 110 // If true, send terrain patch updates to clients based on their view distance
@@ -136,14 +131,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain
136 { 131 {
137 return (updateCount > 0); 132 return (updateCount > 0);
138 } 133 }
134
139 public void SetByXY(int x, int y, bool state) 135 public void SetByXY(int x, int y, bool state)
140 { 136 {
141 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state); 137 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
142 } 138 }
139
143 public bool GetByPatch(int patchX, int patchY) 140 public bool GetByPatch(int patchX, int patchY)
144 { 141 {
145 return updated[patchX, patchY]; 142 return updated[patchX, patchY];
146 } 143 }
144
147 public void SetByPatch(int patchX, int patchY, bool state) 145 public void SetByPatch(int patchX, int patchY, bool state)
148 { 146 {
149 bool prevState = updated[patchX, patchY]; 147 bool prevState = updated[patchX, patchY];
@@ -153,11 +151,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
153 updateCount--; 151 updateCount--;
154 updated[patchX, patchY] = state; 152 updated[patchX, patchY] = state;
155 } 153 }
154
156 public void SetAll(bool state) 155 public void SetAll(bool state)
157 { 156 {
158 updateCount = 0; 157 updateCount = 0;
159 for (int xx = 0; xx < updated.GetLength(0); xx++) 158 for(int xx = 0; xx < updated.GetLength(0); xx++)
160 for (int yy = 0; yy < updated.GetLength(1); yy++) 159 for(int yy = 0; yy < updated.GetLength(1); yy++)
161 updated[xx, yy] = state; 160 updated[xx, yy] = state;
162 if (state) 161 if (state)
163 updateCount = updated.GetLength(0) * updated.GetLength(1); 162 updateCount = updated.GetLength(0) * updated.GetLength(1);
@@ -174,9 +173,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
174 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) 173 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
175 ); 174 );
176 } 175 }
177 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) 176 for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
178 { 177 {
179 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) 178 for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
180 { 179 {
181 // Only set tainted. The patch bit may be set if the patch was to be sent later. 180 // Only set tainted. The patch bit may be set if the patch was to be sent later.
182 if (terrData.IsTaintedAt(xx, yy, false)) 181 if (terrData.IsTaintedAt(xx, yy, false))
@@ -201,8 +200,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
201 200
202 #region ICommandableModule Members 201 #region ICommandableModule Members
203 202
204 public ICommander CommandInterface 203 public ICommander CommandInterface {
205 {
206 get { return m_commander; } 204 get { return m_commander; }
207 } 205 }
208 206
@@ -230,7 +228,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
230 m_scene = scene; 228 m_scene = scene;
231 229
232 // Install terrain module in the simulator 230 // Install terrain module in the simulator
233 lock (m_scene) 231 lock(m_scene)
234 { 232 {
235 if (m_scene.Heightmap == null) 233 if (m_scene.Heightmap == null)
236 { 234 {
@@ -262,7 +260,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
262 string supportedFilesSeparatorForTileSave = ""; 260 string supportedFilesSeparatorForTileSave = "";
263 261
264 m_supportFileExtensionsForTileSave = ""; 262 m_supportFileExtensionsForTileSave = "";
265 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 263 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
266 { 264 {
267 m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; 265 m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")";
268 supportedFilesSeparator = ", "; 266 supportedFilesSeparator = ", ";
@@ -285,7 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
285 283
286 public void RemoveRegion(Scene scene) 284 public void RemoveRegion(Scene scene)
287 { 285 {
288 lock (m_scene) 286 lock(m_scene)
289 { 287 {
290 // remove the commands 288 // remove the commands
291 m_scene.UnregisterModuleCommander(m_commander.Name); 289 m_scene.UnregisterModuleCommander(m_commander.Name);
@@ -304,13 +302,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
304 { 302 {
305 } 303 }
306 304
307 public Type ReplaceableInterface 305 public Type ReplaceableInterface {
308 {
309 get { return null; } 306 get { return null; }
310 } 307 }
311 308
312 public string Name 309 public string Name {
313 {
314 get { return "TerrainModule"; } 310 get { return "TerrainModule"; }
315 } 311 }
316 312
@@ -329,11 +325,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
329 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> 325 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
330 public void LoadFromFile(string filename) 326 public void LoadFromFile(string filename)
331 { 327 {
332 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 328 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
333 { 329 {
334 if (filename.EndsWith(loader.Key)) 330 if (filename.EndsWith(loader.Key))
335 { 331 {
336 lock (m_scene) 332 lock(m_scene)
337 { 333 {
338 try 334 try
339 { 335 {
@@ -349,20 +345,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain
349 m_channel = channel; 345 m_channel = channel;
350 UpdateRevertMap(); 346 UpdateRevertMap();
351 } 347 }
352 catch (NotImplementedException) 348 catch(NotImplementedException)
353 { 349 {
354 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + 350 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
355 " parser does not support file loading. (May be save only)"); 351 " parser does not support file loading. (May be save only)");
356 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); 352 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value));
357 } 353 }
358 catch (FileNotFoundException) 354 catch(FileNotFoundException)
359 { 355 {
360 m_log.Error( 356 m_log.Error(
361 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); 357 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)");
362 throw new TerrainException( 358 throw new TerrainException(
363 String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); 359 String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename));
364 } 360 }
365 catch (ArgumentException e) 361 catch(ArgumentException e)
366 { 362 {
367 m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); 363 m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message);
368 throw new TerrainException( 364 throw new TerrainException(
@@ -386,7 +382,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
386 { 382 {
387 try 383 try
388 { 384 {
389 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 385 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
390 { 386 {
391 if (filename.EndsWith(loader.Key)) 387 if (filename.EndsWith(loader.Key))
392 { 388 {
@@ -396,7 +392,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
396 } 392 }
397 } 393 }
398 } 394 }
399 catch (IOException ioe) 395 catch(IOException ioe)
400 { 396 {
401 m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message)); 397 m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message));
402 } 398 }
@@ -429,11 +425,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
429 public void LoadFromStream(string filename, Vector3 displacement, 425 public void LoadFromStream(string filename, Vector3 displacement,
430 float radianRotation, Vector2 rotationDisplacement, Stream stream) 426 float radianRotation, Vector2 rotationDisplacement, Stream stream)
431 { 427 {
432 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 428 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
433 { 429 {
434 if (filename.EndsWith(loader.Key)) 430 if (filename.EndsWith(loader.Key))
435 { 431 {
436 lock (m_scene) 432 lock(m_scene)
437 { 433 {
438 try 434 try
439 { 435 {
@@ -441,7 +437,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
441 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); 437 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
442 UpdateRevertMap(); 438 UpdateRevertMap();
443 } 439 }
444 catch (NotImplementedException) 440 catch(NotImplementedException)
445 { 441 {
446 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + 442 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
447 " parser does not support file loading. (May be save only)"); 443 " parser does not support file loading. (May be save only)");
@@ -501,7 +497,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
501 { 497 {
502 try 498 try
503 { 499 {
504 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 500 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
505 { 501 {
506 if (filename.EndsWith(loader.Key)) 502 if (filename.EndsWith(loader.Key))
507 { 503 {
@@ -510,7 +506,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
510 } 506 }
511 } 507 }
512 } 508 }
513 catch (NotImplementedException) 509 catch(NotImplementedException)
514 { 510 {
515 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); 511 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented.");
516 throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); 512 throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented"));
@@ -519,12 +515,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
519 515
520 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. 516 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
521 // ITerrainModule.TaintTerrain() 517 // ITerrainModule.TaintTerrain()
522 public void TaintTerrain () 518 public void TaintTerrain()
523 { 519 {
524 lock (m_perClientPatchUpdates) 520 lock(m_perClientPatchUpdates)
525 { 521 {
526 // Set the flags for all clients so the tainted patches will be sent out 522 // Set the flags for all clients so the tainted patches will be sent out
527 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) 523 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values)
528 { 524 {
529 pups.SetAll(m_scene.Heightmap.GetTerrainData()); 525 pups.SetAll(m_scene.Heightmap.GetTerrainData());
530 } 526 }
@@ -539,7 +535,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
539 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 535 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
540 if (presence != null) 536 if (presence != null)
541 { 537 {
542 lock (m_perClientPatchUpdates) 538 lock(m_perClientPatchUpdates)
543 { 539 {
544 PatchUpdates pups; 540 PatchUpdates pups;
545 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) 541 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
@@ -572,7 +568,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
572 return; 568 return;
573 569
574 string[] files = Directory.GetFiles(plugineffectsPath); 570 string[] files = Directory.GetFiles(plugineffectsPath);
575 foreach (string file in files) 571 foreach(string file in files)
576 { 572 {
577 m_log.Info("Loading effects in " + file); 573 m_log.Info("Loading effects in " + file);
578 try 574 try
@@ -580,7 +576,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
580 Assembly library = Assembly.LoadFrom(file); 576 Assembly library = Assembly.LoadFrom(file);
581 LoadPlugins(library); 577 LoadPlugins(library);
582 } 578 }
583 catch (BadImageFormatException) 579 catch(BadImageFormatException)
584 { 580 {
585 } 581 }
586 } 582 }
@@ -588,7 +584,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
588 584
589 private void LoadPlugins(Assembly library) 585 private void LoadPlugins(Assembly library)
590 { 586 {
591 foreach (Type pluginType in library.GetTypes()) 587 foreach(Type pluginType in library.GetTypes())
592 { 588 {
593 try 589 try
594 { 590 {
@@ -610,7 +606,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
610 m_log.Info("L ... " + typeName); 606 m_log.Info("L ... " + typeName);
611 } 607 }
612 } 608 }
613 catch (AmbiguousMatchException) 609 catch(AmbiguousMatchException)
614 { 610 {
615 } 611 }
616 } 612 }
@@ -618,7 +614,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
618 614
619 public void InstallPlugin(string pluginName, ITerrainEffect effect) 615 public void InstallPlugin(string pluginName, ITerrainEffect effect)
620 { 616 {
621 lock (m_plugineffects) 617 lock(m_plugineffects)
622 { 618 {
623 if (!m_plugineffects.ContainsKey(pluginName)) 619 if (!m_plugineffects.ContainsKey(pluginName))
624 { 620 {
@@ -664,6 +660,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
664 // Terrain Feature effects 660 // Terrain Feature effects
665 m_featureEffects["rectangle"] = new RectangleFeature(this); 661 m_featureEffects["rectangle"] = new RectangleFeature(this);
666 662
663 // Terrain Modifier operations
664 m_modifyOperations["min"] = new MinModifier(this);
665 m_modifyOperations["max"] = new MaxModifier(this);
666 m_modifyOperations["raise"] = new RaiseModifier(this);
667 m_modifyOperations["lower"] = new LowerModifier(this);
668 m_modifyOperations["fill"] = new FillModifier(this);
669 m_modifyOperations["smooth"] = new SmoothModifier(this);
670
667 // Filesystem load/save loaders 671 // Filesystem load/save loaders
668 m_loaders[".r32"] = new RAW32(); 672 m_loaders[".r32"] = new RAW32();
669 m_loaders[".f32"] = m_loaders[".r32"]; 673 m_loaders[".f32"] = m_loaders[".r32"];
@@ -707,22 +711,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
707 /// <param name="fileStartY">Where to begin our slice</param> 711 /// <param name="fileStartY">Where to begin our slice</param>
708 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) 712 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY)
709 { 713 {
710 int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX; 714 int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX;
711 int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY; 715 int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY;
712 716
713 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) 717 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight)
714 { 718 {
715 // this region is included in the tile request 719 // this region is included in the tile request
716 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 720 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
717 { 721 {
718 if (filename.EndsWith(loader.Key)) 722 if (filename.EndsWith(loader.Key))
719 { 723 {
720 lock (m_scene) 724 lock(m_scene)
721 { 725 {
722 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 726 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
723 fileWidth, fileHeight, 727 fileWidth, fileHeight,
724 (int) m_scene.RegionInfo.RegionSizeX, 728 (int)m_scene.RegionInfo.RegionSizeX,
725 (int) m_scene.RegionInfo.RegionSizeY); 729 (int)m_scene.RegionInfo.RegionSizeY);
726 m_scene.Heightmap = channel; 730 m_scene.Heightmap = channel;
727 m_channel = channel; 731 m_channel = channel;
728 UpdateRevertMap(); 732 UpdateRevertMap();
@@ -761,11 +765,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
761 } 765 }
762 766
763 // this region is included in the tile request 767 // this region is included in the tile request
764 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 768 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
765 { 769 {
766 if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave()) 770 if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave())
767 { 771 {
768 lock (m_scene) 772 lock(m_scene)
769 { 773 {
770 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, 774 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
771 fileWidth, fileHeight, 775 fileWidth, fileHeight,
@@ -799,9 +803,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
799 TerrainData terrData = m_channel.GetTerrainData(); 803 TerrainData terrData = m_channel.GetTerrainData();
800 804
801 bool shouldTaint = false; 805 bool shouldTaint = false;
802 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 806 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
803 { 807 {
804 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 808 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
805 { 809 {
806 if (terrData.IsTaintedAt(x, y)) 810 if (terrData.IsTaintedAt(x, y))
807 { 811 {
@@ -856,7 +860,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
856 860
857 string[] tmpArgs = new string[args.Length - 2]; 861 string[] tmpArgs = new string[args.Length - 2];
858 int i; 862 int i;
859 for (i = 2; i < args.Length; i++) 863 for(i = 2; i < args.Length; i++)
860 tmpArgs[i - 2] = args[i]; 864 tmpArgs[i - 2] = args[i];
861 865
862 m_commander.ProcessConsoleCommand(args[1], tmpArgs); 866 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
@@ -890,7 +894,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
890 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 894 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
891 } 895 }
892 896
893 lock (m_perClientPatchUpdates) 897 lock(m_perClientPatchUpdates)
894 m_perClientPatchUpdates.Remove(client); 898 m_perClientPatchUpdates.Remove(client);
895 } 899 }
896 900
@@ -904,12 +908,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
904 TerrainData terrData = m_channel.GetTerrainData(); 908 TerrainData terrData = m_channel.GetTerrainData();
905 909
906 bool wasLimited = false; 910 bool wasLimited = false;
907 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 911 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
908 { 912 {
909 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 913 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
910 { 914 {
911 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) 915 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
912 { 916 {
913 // If we should respect the estate settings then 917 // If we should respect the estate settings then
914 // fixup and height deltas that don't respect them. 918 // fixup and height deltas that don't respect them.
915 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. 919 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
@@ -933,9 +937,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
933 937
934 // loop through the height map for this patch and compare it against 938 // loop through the height map for this patch and compare it against
935 // the revert map 939 // the revert map
936 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) 940 for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
937 { 941 {
938 for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 942 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
939 { 943 {
940 float requestedHeight = terrData[x, y]; 944 float requestedHeight = terrData[x, y];
941 float bakedHeight = (float)m_revert[x, y]; 945 float bakedHeight = (float)m_revert[x, y];
@@ -959,7 +963,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
959 963
960 private void client_OnLandUndo(IClientAPI client) 964 private void client_OnLandUndo(IClientAPI client)
961 { 965 {
962 lock (m_undo) 966 lock(m_undo)
963 { 967 {
964 if (m_undo.Count > 0) 968 if (m_undo.Count > 0)
965 { 969 {
@@ -981,19 +985,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
981 if (m_sendTerrainUpdatesByViewDistance) 985 if (m_sendTerrainUpdatesByViewDistance)
982 { 986 {
983 // Add that this patch needs to be sent to the accounting for each client. 987 // Add that this patch needs to be sent to the accounting for each client.
984 lock (m_perClientPatchUpdates) 988 lock(m_perClientPatchUpdates)
985 { 989 {
986 m_scene.ForEachScenePresence(presence => 990 m_scene.ForEachScenePresence(presence =>
991 {
992 PatchUpdates thisClientUpdates;
993 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
987 { 994 {
988 PatchUpdates thisClientUpdates; 995 // There is a ScenePresence without a send patch map. Create one.
989 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) 996 thisClientUpdates = new PatchUpdates(terrData, presence);
990 { 997 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
991 // There is a ScenePresence without a send patch map. Create one.
992 thisClientUpdates = new PatchUpdates(terrData, presence);
993 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
994 }
995 thisClientUpdates.SetByXY(x, y, true);
996 } 998 }
999 thisClientUpdates.SetByXY(x, y, true);
1000 }
997 ); 1001 );
998 } 1002 }
999 } 1003 }
@@ -1005,11 +1009,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1005 float[] heightMap = new float[10]; 1009 float[] heightMap = new float[10];
1006 m_scene.ForEachClient( 1010 m_scene.ForEachClient(
1007 delegate(IClientAPI controller) 1011 delegate(IClientAPI controller)
1008 { 1012 {
1009 controller.SendLayerData(x / Constants.TerrainPatchSize, 1013 controller.SendLayerData(x / Constants.TerrainPatchSize,
1010 y / Constants.TerrainPatchSize, 1014 y / Constants.TerrainPatchSize,
1011 heightMap); 1015 heightMap);
1012 } 1016 }
1013 ); 1017 );
1014 } 1018 }
1015 } 1019 }
@@ -1019,12 +1023,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1019 public int PatchX; 1023 public int PatchX;
1020 public int PatchY; 1024 public int PatchY;
1021 public float Dist; 1025 public float Dist;
1026
1022 public PatchesToSend(int pX, int pY, float pDist) 1027 public PatchesToSend(int pX, int pY, float pDist)
1023 { 1028 {
1024 PatchX = pX; 1029 PatchX = pX;
1025 PatchY = pY; 1030 PatchY = pY;
1026 Dist = pDist; 1031 Dist = pDist;
1027 } 1032 }
1033
1028 public int CompareTo(PatchesToSend other) 1034 public int CompareTo(PatchesToSend other)
1029 { 1035 {
1030 return Dist.CompareTo(other.Dist); 1036 return Dist.CompareTo(other.Dist);
@@ -1036,9 +1042,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1036 // Loop through all the per-client info and send any patches necessary. 1042 // Loop through all the per-client info and send any patches necessary.
1037 private void CheckSendingPatchesToClients() 1043 private void CheckSendingPatchesToClients()
1038 { 1044 {
1039 lock (m_perClientPatchUpdates) 1045 lock(m_perClientPatchUpdates)
1040 { 1046 {
1041 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) 1047 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values)
1042 { 1048 {
1043 if (pups.HasUpdates()) 1049 if (pups.HasUpdates())
1044 { 1050 {
@@ -1062,7 +1068,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1062 int[] yPieces = new int[toSend.Count]; 1068 int[] yPieces = new int[toSend.Count];
1063 float[] patchPieces = new float[toSend.Count * 2]; 1069 float[] patchPieces = new float[toSend.Count * 2];
1064 int pieceIndex = 0; 1070 int pieceIndex = 0;
1065 foreach (PatchesToSend pts in toSend) 1071 foreach(PatchesToSend pts in toSend)
1066 { 1072 {
1067 patchPieces[pieceIndex++] = pts.PatchX; 1073 patchPieces[pieceIndex++] = pts.PatchX;
1068 patchPieces[pieceIndex++] = pts.PatchY; 1074 patchPieces[pieceIndex++] = pts.PatchY;
@@ -1083,25 +1089,25 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1083 return ret; 1089 return ret;
1084 1090
1085 // Compute the area of patches within our draw distance 1091 // Compute the area of patches within our draw distance
1086 int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; 1092 int startX = (((int)(presence.AbsolutePosition.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
1087 startX = Math.Max(startX, 0); 1093 startX = Math.Max(startX, 0);
1088 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); 1094 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
1089 int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; 1095 int startY = (((int)(presence.AbsolutePosition.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
1090 startY = Math.Max(startY, 0); 1096 startY = Math.Max(startY, 0);
1091 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); 1097 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
1092 int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; 1098 int endX = (((int)(presence.AbsolutePosition.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
1093 endX = Math.Max(endX, 0); 1099 endX = Math.Max(endX, 0);
1094 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); 1100 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
1095 int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; 1101 int endY = (((int)(presence.AbsolutePosition.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
1096 endY = Math.Max(endY, 0); 1102 endY = Math.Max(endY, 0);
1097 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); 1103 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
1098 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>", 1104 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
1099 // LogHeader, m_scene.RegionInfo.RegionName, 1105 // LogHeader, m_scene.RegionInfo.RegionName,
1100 // presence.DrawDistance, presence.AbsolutePosition, 1106 // presence.DrawDistance, presence.AbsolutePosition,
1101 // startX, startY, endX, endY); 1107 // startX, startY, endX, endY);
1102 for (int x = startX; x < endX; x++) 1108 for(int x = startX; x < endX; x++)
1103 { 1109 {
1104 for (int y = startY; y < endY; y++) 1110 for(int y = startY; y < endY; y++)
1105 { 1111 {
1106 //Need to make sure we don't send the same ones over and over 1112 //Need to make sure we don't send the same ones over and over
1107 Vector3 presencePos = presence.AbsolutePosition; 1113 Vector3 presencePos = presence.AbsolutePosition;
@@ -1133,28 +1139,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1133 bool allowed = false; 1139 bool allowed = false;
1134 if (north == south && east == west) 1140 if (north == south && east == west)
1135 { 1141 {
1136 if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) 1142 if (m_painteffects.ContainsKey((StandardTerrainEffects)action))
1137 { 1143 {
1138 bool[,] allowMask = new bool[m_channel.Width,m_channel.Height]; 1144 bool[,] allowMask = new bool[m_channel.Width, m_channel.Height];
1139 allowMask.Initialize(); 1145 allowMask.Initialize();
1140 int n = size + 1; 1146 int n = size + 1;
1141 if (n > 2) 1147 if (n > 2)
1142 n = 4; 1148 n = 4;
1143 1149
1144 int zx = (int) (west + 0.5); 1150 int zx = (int)(west + 0.5);
1145 int zy = (int) (north + 0.5); 1151 int zy = (int)(north + 0.5);
1146 1152
1147 int dx; 1153 int dx;
1148 for (dx=-n; dx<=n; dx++) 1154 for(dx=-n; dx<=n; dx++)
1149 { 1155 {
1150 int dy; 1156 int dy;
1151 for (dy=-n; dy<=n; dy++) 1157 for(dy=-n; dy<=n; dy++)
1152 { 1158 {
1153 int x = zx + dx; 1159 int x = zx + dx;
1154 int y = zy + dy; 1160 int y = zy + dy;
1155 if (x>=0 && y>=0 && x<m_channel.Width && y<m_channel.Height) 1161 if (x >= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height)
1156 { 1162 {
1157 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) 1163 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1158 { 1164 {
1159 allowMask[x, y] = true; 1165 allowMask[x, y] = true;
1160 allowed = true; 1166 allowed = true;
@@ -1165,7 +1171,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1165 if (allowed) 1171 if (allowed)
1166 { 1172 {
1167 StoreUndoState(); 1173 StoreUndoState();
1168 m_painteffects[(StandardTerrainEffects) action].PaintEffect( 1174 m_painteffects[(StandardTerrainEffects)action].PaintEffect(
1169 m_channel, allowMask, west, south, height, size, seconds); 1175 m_channel, allowMask, west, south, height, size, seconds);
1170 1176
1171 //revert changes outside estate limits 1177 //revert changes outside estate limits
@@ -1180,22 +1186,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1180 } 1186 }
1181 else 1187 else
1182 { 1188 {
1183 if (m_floodeffects.ContainsKey((StandardTerrainEffects) action)) 1189 if (m_floodeffects.ContainsKey((StandardTerrainEffects)action))
1184 { 1190 {
1185 bool[,] fillArea = new bool[m_channel.Width,m_channel.Height]; 1191 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
1186 fillArea.Initialize(); 1192 fillArea.Initialize();
1187 1193
1188 int x; 1194 int x;
1189 for (x = 0; x < m_channel.Width; x++) 1195 for(x = 0; x < m_channel.Width; x++)
1190 { 1196 {
1191 int y; 1197 int y;
1192 for (y = 0; y < m_channel.Height; y++) 1198 for(y = 0; y < m_channel.Height; y++)
1193 { 1199 {
1194 if (x < east && x > west) 1200 if (x < east && x > west)
1195 { 1201 {
1196 if (y < north && y > south) 1202 if (y < north && y > south)
1197 { 1203 {
1198 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) 1204 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1199 { 1205 {
1200 fillArea[x, y] = true; 1206 fillArea[x, y] = true;
1201 allowed = true; 1207 allowed = true;
@@ -1208,7 +1214,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1208 if (allowed) 1214 if (allowed)
1209 { 1215 {
1210 StoreUndoState(); 1216 StoreUndoState();
1211 m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size); 1217 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size);
1212 1218
1213 //revert changes outside estate limits 1219 //revert changes outside estate limits
1214 if (!god) 1220 if (!god)
@@ -1243,7 +1249,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1243 1249
1244 private void StoreUndoState() 1250 private void StoreUndoState()
1245 { 1251 {
1246 lock (m_undo) 1252 lock(m_undo)
1247 { 1253 {
1248 if (m_undo.Count > 0) 1254 if (m_undo.Count > 0)
1249 { 1255 {
@@ -1264,21 +1270,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1264 1270
1265 private void InterfaceLoadFile(Object[] args) 1271 private void InterfaceLoadFile(Object[] args)
1266 { 1272 {
1267 LoadFromFile((string) args[0]); 1273 LoadFromFile((string)args[0]);
1268 } 1274 }
1269 1275
1270 private void InterfaceLoadTileFile(Object[] args) 1276 private void InterfaceLoadTileFile(Object[] args)
1271 { 1277 {
1272 LoadFromFile((string) args[0], 1278 LoadFromFile((string)args[0],
1273 (int) args[1], 1279 (int)args[1],
1274 (int) args[2], 1280 (int)args[2],
1275 (int) args[3], 1281 (int)args[3],
1276 (int) args[4]); 1282 (int)args[4]);
1277 } 1283 }
1278 1284
1279 private void InterfaceSaveFile(Object[] args) 1285 private void InterfaceSaveFile(Object[] args)
1280 { 1286 {
1281 SaveToFile((string) args[0]); 1287 SaveToFile((string)args[0]);
1282 } 1288 }
1283 1289
1284 private void InterfaceSaveTileFile(Object[] args) 1290 private void InterfaceSaveTileFile(Object[] args)
@@ -1298,8 +1304,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1298 private void InterfaceRevertTerrain(Object[] args) 1304 private void InterfaceRevertTerrain(Object[] args)
1299 { 1305 {
1300 int x, y; 1306 int x, y;
1301 for (x = 0; x < m_channel.Width; x++) 1307 for(x = 0; x < m_channel.Width; x++)
1302 for (y = 0; y < m_channel.Height; y++) 1308 for(y = 0; y < m_channel.Height; y++)
1303 m_channel[x, y] = m_revert[x, y]; 1309 m_channel[x, y] = m_revert[x, y];
1304 1310
1305 } 1311 }
@@ -1310,9 +1316,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1310 1316
1311 if (direction.ToLower().StartsWith("y")) 1317 if (direction.ToLower().StartsWith("y"))
1312 { 1318 {
1313 for (int x = 0; x < m_channel.Width; x++) 1319 for(int x = 0; x < m_channel.Width; x++)
1314 { 1320 {
1315 for (int y = 0; y < m_channel.Height / 2; y++) 1321 for(int y = 0; y < m_channel.Height / 2; y++)
1316 { 1322 {
1317 double height = m_channel[x, y]; 1323 double height = m_channel[x, y];
1318 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; 1324 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
@@ -1324,9 +1330,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1324 } 1330 }
1325 else if (direction.ToLower().StartsWith("x")) 1331 else if (direction.ToLower().StartsWith("x"))
1326 { 1332 {
1327 for (int y = 0; y < m_channel.Height; y++) 1333 for(int y = 0; y < m_channel.Height; y++)
1328 { 1334 {
1329 for (int x = 0; x < m_channel.Width / 2; x++) 1335 for(int x = 0; x < m_channel.Width / 2; x++)
1330 { 1336 {
1331 double height = m_channel[x, y]; 1337 double height = m_channel[x, y];
1332 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; 1338 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
@@ -1365,9 +1371,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1365 int width = m_channel.Width; 1371 int width = m_channel.Width;
1366 int height = m_channel.Height; 1372 int height = m_channel.Height;
1367 1373
1368 for (int x = 0; x < width; x++) 1374 for(int x = 0; x < width; x++)
1369 { 1375 {
1370 for (int y = 0; y < height; y++) 1376 for(int y = 0; y < height; y++)
1371 { 1377 {
1372 double currHeight = m_channel[x, y]; 1378 double currHeight = m_channel[x, y];
1373 if (currHeight < currMin) 1379 if (currHeight < currMin)
@@ -1388,12 +1394,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1388 //m_log.InfoFormat("Scale = {0}", scale); 1394 //m_log.InfoFormat("Scale = {0}", scale);
1389 1395
1390 // scale the heightmap accordingly 1396 // scale the heightmap accordingly
1391 for (int x = 0; x < width; x++) 1397 for(int x = 0; x < width; x++)
1392 { 1398 {
1393 for (int y = 0; y < height; y++) 1399 for(int y = 0; y < height; y++)
1394 { 1400 {
1395 double currHeight = m_channel[x, y] - currMin; 1401 double currHeight = m_channel[x, y] - currMin;
1396 m_channel[x, y] = desiredMin + (currHeight * scale); 1402 m_channel[x, y] = desiredMin + (currHeight * scale);
1397 } 1403 }
1398 } 1404 }
1399 1405
@@ -1404,42 +1410,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1404 private void InterfaceElevateTerrain(Object[] args) 1410 private void InterfaceElevateTerrain(Object[] args)
1405 { 1411 {
1406 int x, y; 1412 int x, y;
1407 for (x = 0; x < m_channel.Width; x++) 1413 for(x = 0; x < m_channel.Width; x++)
1408 for (y = 0; y < m_channel.Height; y++) 1414 for(y = 0; y < m_channel.Height; y++)
1409 m_channel[x, y] += (double) args[0]; 1415 m_channel[x, y] += (double)args[0];
1410 } 1416 }
1411 1417
1412 private void InterfaceMultiplyTerrain(Object[] args) 1418 private void InterfaceMultiplyTerrain(Object[] args)
1413 { 1419 {
1414 int x, y; 1420 int x, y;
1415 for (x = 0; x < m_channel.Width; x++) 1421 for(x = 0; x < m_channel.Width; x++)
1416 for (y = 0; y < m_channel.Height; y++) 1422 for(y = 0; y < m_channel.Height; y++)
1417 m_channel[x, y] *= (double) args[0]; 1423 m_channel[x, y] *= (double)args[0];
1418 } 1424 }
1419 1425
1420 private void InterfaceLowerTerrain(Object[] args) 1426 private void InterfaceLowerTerrain(Object[] args)
1421 { 1427 {
1422 int x, y; 1428 int x, y;
1423 for (x = 0; x < m_channel.Width; x++) 1429 for(x = 0; x < m_channel.Width; x++)
1424 for (y = 0; y < m_channel.Height; y++) 1430 for(y = 0; y < m_channel.Height; y++)
1425 m_channel[x, y] -= (double) args[0]; 1431 m_channel[x, y] -= (double)args[0];
1426 } 1432 }
1427 1433
1428 public void InterfaceFillTerrain(Object[] args) 1434 public void InterfaceFillTerrain(Object[] args)
1429 { 1435 {
1430 int x, y; 1436 int x, y;
1431 1437
1432 for (x = 0; x < m_channel.Width; x++) 1438 for(x = 0; x < m_channel.Width; x++)
1433 for (y = 0; y < m_channel.Height; y++) 1439 for(y = 0; y < m_channel.Height; y++)
1434 m_channel[x, y] = (double) args[0]; 1440 m_channel[x, y] = (double)args[0];
1435 } 1441 }
1436 1442
1437 private void InterfaceMinTerrain(Object[] args) 1443 private void InterfaceMinTerrain(Object[] args)
1438 { 1444 {
1439 int x, y; 1445 int x, y;
1440 for (x = 0; x < m_channel.Width; x++) 1446 for(x = 0; x < m_channel.Width; x++)
1441 { 1447 {
1442 for (y = 0; y < m_channel.Height; y++) 1448 for(y = 0; y < m_channel.Height; y++)
1443 { 1449 {
1444 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1450 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
1445 } 1451 }
@@ -1449,9 +1455,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1449 private void InterfaceMaxTerrain(Object[] args) 1455 private void InterfaceMaxTerrain(Object[] args)
1450 { 1456 {
1451 int x, y; 1457 int x, y;
1452 for (x = 0; x < m_channel.Width; x++) 1458 for(x = 0; x < m_channel.Width; x++)
1453 { 1459 {
1454 for (y = 0; y < m_channel.Height; y++) 1460 for(y = 0; y < m_channel.Height; y++)
1455 { 1461 {
1456 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1462 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
1457 } 1463 }
@@ -1480,10 +1486,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1480 double sum = 0; 1486 double sum = 0;
1481 1487
1482 int x; 1488 int x;
1483 for (x = 0; x < m_channel.Width; x++) 1489 for(x = 0; x < m_channel.Width; x++)
1484 { 1490 {
1485 int y; 1491 int y;
1486 for (y = 0; y < m_channel.Height; y++) 1492 for(y = 0; y < m_channel.Height; y++)
1487 { 1493 {
1488 sum += m_channel[x, y]; 1494 sum += m_channel[x, y];
1489 if (max < m_channel[x, y]) 1495 if (max < m_channel[x, y])
@@ -1501,7 +1507,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1501 1507
1502 private void InterfaceEnableExperimentalBrushes(Object[] args) 1508 private void InterfaceEnableExperimentalBrushes(Object[] args)
1503 { 1509 {
1504 if ((bool) args[0]) 1510 if ((bool)args[0])
1505 { 1511 {
1506 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); 1512 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere();
1507 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); 1513 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere();
@@ -1520,7 +1526,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1520 if (firstArg == "list") 1526 if (firstArg == "list")
1521 { 1527 {
1522 MainConsole.Instance.Output("List of loaded plugins"); 1528 MainConsole.Instance.Output("List of loaded plugins");
1523 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1529 foreach(KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
1524 { 1530 {
1525 MainConsole.Instance.Output(kvp.Key); 1531 MainConsole.Instance.Output(kvp.Key);
1526 } 1532 }
@@ -1668,6 +1674,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1668 // Add Feature command to Scene, since Command object requires fixed-length arglists 1674 // Add Feature command to Scene, since Command object requires fixed-length arglists
1669 m_scene.AddCommand("Terrain", this, "terrain feature", 1675 m_scene.AddCommand("Terrain", this, "terrain feature",
1670 "terrain feature <type> <parameters...>", "Constructs a feature of the requested type.", FeatureCommand); 1676 "terrain feature <type> <parameters...>", "Constructs a feature of the requested type.", FeatureCommand);
1677 // Add Modify command to Scene, since Command object requires fixed-length arglists
1678 m_scene.AddCommand("Terrain", this, "terrain modify",
1679 "terrain modify <operation> <value> [<area>] [<taper>]",
1680 "Modifies the terrain as instructed." +
1681 "\nEach operation can be limited to an area of effect:" +
1682 "\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" +
1683 "\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" +
1684 "\nEach operation can have its effect tapered based on distance from centre:" +
1685 "\n * elliptical operations taper as cones" +
1686 "\n * rectangular operations taper as pyramids"
1687 ,
1688 ModifyCommand);
1671 1689
1672 } 1690 }
1673 1691
@@ -1683,7 +1701,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1683 { 1701 {
1684 result = String.Format("Terrain Feature \"{0}\" not found.", featureType); 1702 result = String.Format("Terrain Feature \"{0}\" not found.", featureType);
1685 } 1703 }
1686 else if ((cmd.Length > 3) && (cmd[3] == "usage")) 1704 else if ((cmd.Length > 3) && (cmd[3] == "usage"))
1687 { 1705 {
1688 result = "Usage: " + feature.GetUsage(); 1706 result = "Usage: " + feature.GetUsage();
1689 } 1707 }
@@ -1692,7 +1710,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1692 result = feature.CreateFeature(m_channel, cmd); 1710 result = feature.CreateFeature(m_channel, cmd);
1693 } 1711 }
1694 1712
1695 if(result == String.Empty) 1713 if (result == String.Empty)
1696 { 1714 {
1697 result = "Created Feature"; 1715 result = "Created Feature";
1698 m_log.DebugFormat("Created terrain feature {0}", featureType); 1716 m_log.DebugFormat("Created terrain feature {0}", featureType);
@@ -1704,7 +1722,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1704 } 1722 }
1705 MainConsole.Instance.Output(result); 1723 MainConsole.Instance.Output(result);
1706 } 1724 }
1707 #endregion 1725
1726 public void ModifyCommand(string module, string[] cmd)
1727 {
1728 string result;
1729 if (cmd.Length > 2)
1730 {
1731 string operationType = cmd[2];
1732
1733 ITerrainModifier operation;
1734 if (!m_modifyOperations.TryGetValue(operationType, out operation))
1735 {
1736 result = String.Format("Terrain Modify \"{0}\" not found.", operationType);
1737 }
1738 else if ((cmd.Length > 3) && (cmd[3] == "usage"))
1739 {
1740 result = "Usage: " + operation.GetUsage();
1741 }
1742 else
1743 {
1744 result = operation.ModifyTerrain(m_channel, cmd);
1745 }
1746
1747 if (result == String.Empty)
1748 {
1749 result = "Modified terrain";
1750 m_log.DebugFormat("Performed terrain operation {0}", operationType);
1751 }
1752 }
1753 else
1754 {
1755 result = "Usage: <operation-name> <arg1> <arg2>...";
1756 }
1757 MainConsole.Instance.Output(result);
1758 }
1759
1760#endregion
1708 1761
1709 } 1762 }
1710} 1763}