aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs642
1 files changed, 367 insertions, 275 deletions
diff --git a/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs b/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs
index 27bfb36..987c3d0 100644
--- a/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs
@@ -27,18 +27,29 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.IO;
31using System.Reflection;
31using libsecondlife; 32using libsecondlife;
33using log4net;
32using Nini.Config; 34using Nini.Config;
33using OpenSim.Framework; 35using OpenSim.Framework;
34using OpenSim.Region.Environment.Interfaces; 36using OpenSim.Region.Environment.Interfaces;
35using OpenSim.Region.Environment.Scenes;
36using OpenSim.Region.Environment.Modules.ModuleFramework; 37using OpenSim.Region.Environment.Modules.ModuleFramework;
38using OpenSim.Region.Environment.Modules.Terrain.Effects;
39using OpenSim.Region.Environment.Modules.Terrain.FileLoaders;
40using OpenSim.Region.Environment.Modules.Terrain.FloodBrushes;
41using OpenSim.Region.Environment.Modules.Terrain.PaintBrushes;
42using OpenSim.Region.Environment.Scenes;
37 43
38namespace OpenSim.Region.Environment.Modules.Terrain 44namespace OpenSim.Region.Environment.Modules.Terrain
39{ 45{
40 public class TerrainModule : IRegionModule, ICommandableModule, OpenSim.Region.Environment.Modules.Terrain.ITerrainModule 46 public class TerrainModule : IRegionModule, ICommandableModule, ITerrainModule
41 { 47 {
48 #region StandardTerrainEffects enum
49
50 /// <summary>
51 /// A standard set of terrain brushes and effects recognised by viewers
52 /// </summary>
42 public enum StandardTerrainEffects : byte 53 public enum StandardTerrainEffects : byte
43 { 54 {
44 Flatten = 0, 55 Flatten = 0,
@@ -54,68 +65,100 @@ namespace OpenSim.Region.Environment.Modules.Terrain
54 Olsen = 253 65 Olsen = 253
55 } 66 }
56 67
57 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 68 #endregion
58 69
59 private Commander m_commander = new Commander("Terrain"); 70 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 71
61 private Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 72 private readonly Commander m_commander = new Commander("Terrain");
62 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 73
63 private Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects = 74 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
64 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>(); 75 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
65 private Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
66 Scene m_scene;
67 ITerrainChannel m_channel;
68 ITerrainChannel m_revert;
69 bool m_tainted = false;
70 private IConfigSource m_gConfig;
71 76
72 private void InstallDefaultEffects() 77 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
73 {
74 // Draggable Paint Brush Effects
75 m_painteffects[StandardTerrainEffects.Raise] = new PaintBrushes.RaiseSphere();
76 m_painteffects[StandardTerrainEffects.Lower] = new PaintBrushes.LowerSphere();
77 m_painteffects[StandardTerrainEffects.Smooth] = new PaintBrushes.SmoothSphere();
78 m_painteffects[StandardTerrainEffects.Noise] = new PaintBrushes.NoiseSphere();
79 m_painteffects[StandardTerrainEffects.Flatten] = new PaintBrushes.FlattenSphere();
80 m_painteffects[StandardTerrainEffects.Revert] = new PaintBrushes.RevertSphere(m_revert);
81 m_painteffects[StandardTerrainEffects.Erode] = new PaintBrushes.ErodeSphere();
82 m_painteffects[StandardTerrainEffects.Weather] = new PaintBrushes.WeatherSphere();
83 m_painteffects[StandardTerrainEffects.Olsen] = new PaintBrushes.OlsenSphere();
84 78
85 // Area of effect selection effects 79 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
86 m_floodeffects[StandardTerrainEffects.Raise] = new FloodBrushes.RaiseArea(); 80 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
87 m_floodeffects[StandardTerrainEffects.Lower] = new FloodBrushes.LowerArea();
88 m_floodeffects[StandardTerrainEffects.Smooth] = new FloodBrushes.SmoothArea();
89 m_floodeffects[StandardTerrainEffects.Noise] = new FloodBrushes.NoiseArea();
90 m_floodeffects[StandardTerrainEffects.Flatten] = new FloodBrushes.FlattenArea();
91 m_floodeffects[StandardTerrainEffects.Revert] = new FloodBrushes.RevertArea(m_revert);
92 81
93 // Filesystem load/save loaders 82 private ITerrainChannel m_channel;
94 m_loaders[".r32"] = new FileLoaders.RAW32(); 83 private ITerrainChannel m_revert;
95 m_loaders[".f32"] = m_loaders[".r32"]; 84 private Scene m_scene;
96 m_loaders[".ter"] = new FileLoaders.Terragen(); 85 private bool m_tainted = false;
97 m_loaders[".raw"] = new FileLoaders.LLRAW(); 86
98 m_loaders[".jpg"] = new FileLoaders.JPEG(); 87 #region ICommandableModule Members
99 m_loaders[".jpeg"] = m_loaders[".jpg"]; 88
100 m_loaders[".bmp"] = new FileLoaders.BMP(); 89 public ICommander CommandInterface
101 m_loaders[".png"] = new FileLoaders.PNG(); 90 {
102 m_loaders[".gif"] = new FileLoaders.GIF(); 91 get { return m_commander; }
103 m_loaders[".tif"] = new FileLoaders.TIFF();
104 m_loaders[".tiff"] = m_loaders[".tif"];
105 } 92 }
106 93
107 public void UpdateRevertMap() 94 #endregion
95
96 #region IRegionModule Members
97
98 /// <summary>
99 /// Creates and initialises a terrain module for a region
100 /// </summary>
101 /// <param name="scene">Region initialising</param>
102 /// <param name="config">Config for the region</param>
103 public void Initialise(Scene scene, IConfigSource config)
108 { 104 {
109 int x, y; 105 m_scene = scene;
110 for (x = 0; x < m_channel.Width; x++) 106
107 // Install terrain module in the simulator
108 if (m_scene.Heightmap == null)
111 { 109 {
112 for (y = 0; y < m_channel.Height; y++) 110 lock (m_scene)
113 { 111 {
114 m_revert[x, y] = m_channel[x, y]; 112 m_channel = new TerrainChannel();
113 m_scene.Heightmap = m_channel;
114 m_revert = new TerrainChannel();
115 UpdateRevertMap();
115 } 116 }
116 } 117 }
118 else
119 {
120 m_channel = m_scene.Heightmap;
121 m_revert = new TerrainChannel();
122 UpdateRevertMap();
123 }
124
125 m_scene.RegisterModuleInterface<ITerrainModule>(this);
126 m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
127 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
128 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
129 }
130
131 /// <summary>
132 /// Enables terrain module when called
133 /// </summary>
134 public void PostInitialise()
135 {
136 InstallDefaultEffects();
137 InstallInterfaces();
138 }
139
140 public void Close()
141 {
142 }
143
144 public string Name
145 {
146 get { return "TerrainModule"; }
117 } 147 }
118 148
149 public bool IsSharedModule
150 {
151 get { return false; }
152 }
153
154 #endregion
155
156 #region ITerrainModule Members
157
158 /// <summary>
159 /// Loads a terrain file from disk and installs it in the scene.
160 /// </summary>
161 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
119 public void LoadFromFile(string filename) 162 public void LoadFromFile(string filename)
120 { 163 {
121 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 164 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
@@ -133,12 +176,14 @@ namespace OpenSim.Region.Environment.Modules.Terrain
133 } 176 }
134 catch (NotImplementedException) 177 catch (NotImplementedException)
135 { 178 {
136 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value.ToString() + " parser does not support file loading. (May be save only)"); 179 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
180 " parser does not support file loading. (May be save only)");
137 return; 181 return;
138 } 182 }
139 catch (System.IO.FileNotFoundException) 183 catch (FileNotFoundException)
140 { 184 {
141 m_log.Error("[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); 185 m_log.Error(
186 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)");
142 return; 187 return;
143 } 188 }
144 } 189 }
@@ -149,10 +194,97 @@ namespace OpenSim.Region.Environment.Modules.Terrain
149 m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader availible for that format."); 194 m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader availible for that format.");
150 } 195 }
151 196
197 /// <summary>
198 /// Saves the current heightmap to a specified file.
199 /// </summary>
200 /// <param name="filename">The destination filename</param>
201 public void SaveToFile(string filename)
202 {
203 try
204 {
205 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
206 {
207 if (filename.EndsWith(loader.Key))
208 {
209 loader.Value.SaveFile(filename, m_channel);
210 return;
211 }
212 }
213 }
214 catch (NotImplementedException)
215 {
216 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented.");
217 }
218 }
219
220 #endregion
221
222 /// <summary>
223 /// Installs into terrain module the standard suite of brushes
224 /// </summary>
225 private void InstallDefaultEffects()
226 {
227 // Draggable Paint Brush Effects
228 m_painteffects[StandardTerrainEffects.Raise] = new RaiseSphere();
229 m_painteffects[StandardTerrainEffects.Lower] = new LowerSphere();
230 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere();
231 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere();
232 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere();
233 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert);
234 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere();
235 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere();
236 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere();
237
238 // Area of effect selection effects
239 m_floodeffects[StandardTerrainEffects.Raise] = new RaiseArea();
240 m_floodeffects[StandardTerrainEffects.Lower] = new LowerArea();
241 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea();
242 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea();
243 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
244 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert);
245
246 // Filesystem load/save loaders
247 m_loaders[".r32"] = new RAW32();
248 m_loaders[".f32"] = m_loaders[".r32"];
249 m_loaders[".ter"] = new Terragen();
250 m_loaders[".raw"] = new LLRAW();
251 m_loaders[".jpg"] = new JPEG();
252 m_loaders[".jpeg"] = m_loaders[".jpg"];
253 m_loaders[".bmp"] = new BMP();
254 m_loaders[".png"] = new PNG();
255 m_loaders[".gif"] = new GIF();
256 m_loaders[".tif"] = new TIFF();
257 m_loaders[".tiff"] = m_loaders[".tif"];
258 }
259
260 /// <summary>
261 /// Saves the current state of the region into the revert map buffer.
262 /// </summary>
263 public void UpdateRevertMap()
264 {
265 int x;
266 for (x = 0; x < m_channel.Width; x++)
267 {
268 int y;
269 for (y = 0; y < m_channel.Height; y++)
270 {
271 m_revert[x, y] = m_channel[x, y];
272 }
273 }
274 }
275
276 /// <summary>
277 /// Loads a tile from a larger terrain file and installs it into the region.
278 /// </summary>
279 /// <param name="filename">The terrain file to load</param>
280 /// <param name="fileWidth">The width of the file in units</param>
281 /// <param name="fileHeight">The height of the file in units</param>
282 /// <param name="fileStartX">Where to begin our slice</param>
283 /// <param name="fileStartY">Where to begin our slice</param>
152 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) 284 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY)
153 { 285 {
154 int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX; 286 int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX;
155 int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY; 287 int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY;
156 288
157 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) 289 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight)
158 { 290 {
@@ -164,7 +296,9 @@ namespace OpenSim.Region.Environment.Modules.Terrain
164 lock (m_scene) 296 lock (m_scene)
165 { 297 {
166 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 298 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
167 fileWidth, fileHeight, (int)Constants.RegionSize, (int)Constants.RegionSize); 299 fileWidth, fileHeight,
300 (int) Constants.RegionSize,
301 (int) Constants.RegionSize);
168 m_scene.Heightmap = channel; 302 m_scene.Heightmap = channel;
169 m_channel = channel; 303 m_channel = channel;
170 UpdateRevertMap(); 304 UpdateRevertMap();
@@ -175,61 +309,137 @@ namespace OpenSim.Region.Environment.Modules.Terrain
175 } 309 }
176 } 310 }
177 311
178 public void SaveToFile(string filename) 312 /// <summary>
313 /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections
314 /// </summary>
315 private void EventManager_OnTerrainTick()
179 { 316 {
180 try 317 if (m_tainted)
181 { 318 {
182 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 319 m_tainted = false;
183 { 320 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
184 if (filename.EndsWith(loader.Key)) 321 m_scene.SaveTerrain();
185 { 322 m_scene.CreateTerrainTexture(true);
186 loader.Value.SaveFile(filename, m_channel);
187 return;
188 }
189 }
190 } 323 }
191 catch (NotImplementedException) 324 }
325
326 /// <summary>
327 /// Processes commandline input. Do not call directly.
328 /// </summary>
329 /// <param name="args">Commandline arguments</param>
330 private void EventManager_OnPluginConsole(string[] args)
331 {
332 if (args[0] == "terrain")
192 { 333 {
193 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); 334 string[] tmpArgs = new string[args.Length - 2];
335 int i;
336 for (i = 2; i < args.Length; i++)
337 tmpArgs[i - 2] = args[i];
338
339 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
194 } 340 }
195 } 341 }
196 342
197 public void Initialise(Scene scene, IConfigSource config) 343 /// <summary>
344 /// Installs terrain brush hook to IClientAPI
345 /// </summary>
346 /// <param name="client"></param>
347 private void EventManager_OnNewClient(IClientAPI client)
198 { 348 {
199 m_scene = scene; 349 client.OnModifyTerrain += client_OnModifyTerrain;
200 m_gConfig = config; 350 }
201 351
202 // Install terrain module in the simulator 352 /// <summary>
203 if (m_scene.Heightmap == null) 353 /// Checks to see if the terrain has been modified since last check
354 /// </summary>
355 private void CheckForTerrainUpdates()
356 {
357 bool shouldTaint = false;
358 float[] serialised = m_channel.GetFloatsSerialised();
359 int x;
360 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
204 { 361 {
205 lock (m_scene) 362 int y;
363 for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize)
206 { 364 {
207 m_channel = new TerrainChannel(); 365 if (m_channel.Tainted(x, y))
208 m_scene.Heightmap = m_channel; 366 {
209 m_revert = new TerrainChannel(); 367 SendToClients(serialised, x, y);
210 UpdateRevertMap(); 368 shouldTaint = true;
369 }
211 } 370 }
212 } 371 }
213 else 372 if (shouldTaint)
214 { 373 {
215 m_channel = m_scene.Heightmap; 374 m_tainted = true;
216 m_revert = new TerrainChannel();
217 UpdateRevertMap();
218 } 375 }
376 }
219 377
220 m_scene.RegisterModuleInterface<ITerrainModule>(this); 378 /// <summary>
221 m_scene.EventManager.OnNewClient += EventManager_OnNewClient; 379 /// Sends a copy of the current terrain to the scenes clients
222 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 380 /// </summary>
223 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; 381 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
382 /// <param name="x">The patch corner to send</param>
383 /// <param name="y">The patch corner to send</param>
384 private void SendToClients(float[] serialised, int x, int y)
385 {
386 m_scene.ForEachClient(
387 delegate(IClientAPI controller) { controller.SendLayerData(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised); });
224 } 388 }
225 389
226 void EventManager_OnTerrainTick() 390 private void client_OnModifyTerrain(float height, float seconds, byte size, byte action, float north, float west,
391 float south, float east, IClientAPI remoteClient)
227 { 392 {
228 if (m_tainted) 393 // Not a good permissions check, if in area mode, need to check the entire area.
394 if (m_scene.PermissionsMngr.CanTerraform(remoteClient.AgentId, new LLVector3(north, west, 0)))
229 { 395 {
230 m_tainted = false; 396 if (north == south && east == west)
231 m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); 397 {
232 m_scene.SaveTerrain(); 398 if (m_painteffects.ContainsKey((StandardTerrainEffects) action))
399 {
400 m_painteffects[(StandardTerrainEffects) action].PaintEffect(
401 m_channel, west, south, size, seconds);
402
403 CheckForTerrainUpdates();
404 }
405 else
406 {
407 m_log.Debug("Unknown terrain brush type " + action);
408 }
409 }
410 else
411 {
412 if (m_floodeffects.ContainsKey((StandardTerrainEffects) action))
413 {
414 bool[,] fillArea = new bool[m_channel.Width,m_channel.Height];
415 fillArea.Initialize();
416
417 int x;
418 for (x = 0; x < m_channel.Width; x++)
419 {
420 int y;
421 for (y = 0; y < m_channel.Height; y++)
422 {
423 if (x < east && x > west)
424 {
425 if (y < north && y > south)
426 {
427 fillArea[x, y] = true;
428 }
429 }
430 }
431 }
432
433 m_floodeffects[(StandardTerrainEffects) action].FloodEffect(
434 m_channel, fillArea, size);
435
436 CheckForTerrainUpdates();
437 }
438 else
439 {
440 m_log.Debug("Unknown terrain flood type " + action);
441 }
442 }
233 } 443 }
234 } 444 }
235 445
@@ -237,23 +447,23 @@ namespace OpenSim.Region.Environment.Modules.Terrain
237 447
238 private void InterfaceLoadFile(Object[] args) 448 private void InterfaceLoadFile(Object[] args)
239 { 449 {
240 LoadFromFile((string)args[0]); 450 LoadFromFile((string) args[0]);
241 CheckForTerrainUpdates(); 451 CheckForTerrainUpdates();
242 } 452 }
243 453
244 private void InterfaceLoadTileFile(Object[] args) 454 private void InterfaceLoadTileFile(Object[] args)
245 { 455 {
246 LoadFromFile((string)args[0], 456 LoadFromFile((string) args[0],
247 (int)args[1], 457 (int) args[1],
248 (int)args[2], 458 (int) args[2],
249 (int)args[3], 459 (int) args[3],
250 (int)args[4]); 460 (int) args[4]);
251 CheckForTerrainUpdates(); 461 CheckForTerrainUpdates();
252 } 462 }
253 463
254 private void InterfaceSaveFile(Object[] args) 464 private void InterfaceSaveFile(Object[] args)
255 { 465 {
256 SaveToFile((string)args[0]); 466 SaveToFile((string) args[0]);
257 } 467 }
258 468
259 private void InterfaceBakeTerrain(Object[] args) 469 private void InterfaceBakeTerrain(Object[] args)
@@ -276,7 +486,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
276 int x, y; 486 int x, y;
277 for (x = 0; x < m_channel.Width; x++) 487 for (x = 0; x < m_channel.Width; x++)
278 for (y = 0; y < m_channel.Height; y++) 488 for (y = 0; y < m_channel.Height; y++)
279 m_channel[x, y] += (double)args[0]; 489 m_channel[x, y] += (double) args[0];
280 CheckForTerrainUpdates(); 490 CheckForTerrainUpdates();
281 } 491 }
282 492
@@ -285,7 +495,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
285 int x, y; 495 int x, y;
286 for (x = 0; x < m_channel.Width; x++) 496 for (x = 0; x < m_channel.Width; x++)
287 for (y = 0; y < m_channel.Height; y++) 497 for (y = 0; y < m_channel.Height; y++)
288 m_channel[x, y] *= (double)args[0]; 498 m_channel[x, y] *= (double) args[0];
289 CheckForTerrainUpdates(); 499 CheckForTerrainUpdates();
290 } 500 }
291 501
@@ -294,7 +504,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
294 int x, y; 504 int x, y;
295 for (x = 0; x < m_channel.Width; x++) 505 for (x = 0; x < m_channel.Width; x++)
296 for (y = 0; y < m_channel.Height; y++) 506 for (y = 0; y < m_channel.Height; y++)
297 m_channel[x, y] -= (double)args[0]; 507 m_channel[x, y] -= (double) args[0];
298 CheckForTerrainUpdates(); 508 CheckForTerrainUpdates();
299 } 509 }
300 510
@@ -304,7 +514,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
304 514
305 for (x = 0; x < m_channel.Width; x++) 515 for (x = 0; x < m_channel.Width; x++)
306 for (y = 0; y < m_channel.Height; y++) 516 for (y = 0; y < m_channel.Height; y++)
307 m_channel[x, y] = (double)args[0]; 517 m_channel[x, y] = (double) args[0];
308 CheckForTerrainUpdates(); 518 CheckForTerrainUpdates();
309 } 519 }
310 520
@@ -312,12 +522,13 @@ namespace OpenSim.Region.Environment.Modules.Terrain
312 { 522 {
313 double max = Double.MinValue; 523 double max = Double.MinValue;
314 double min = double.MaxValue; 524 double min = double.MaxValue;
315 double avg = 0; 525 double avg;
316 double sum = 0; 526 double sum = 0;
317 527
318 int x, y; 528 int x;
319 for (x = 0; x < m_channel.Width; x++) 529 for (x = 0; x < m_channel.Width; x++)
320 { 530 {
531 int y;
321 for (y = 0; y < m_channel.Height; y++) 532 for (y = 0; y < m_channel.Height; y++)
322 { 533 {
323 sum += m_channel[x, y]; 534 sum += m_channel[x, y];
@@ -336,11 +547,11 @@ namespace OpenSim.Region.Environment.Modules.Terrain
336 547
337 private void InterfaceEnableExperimentalBrushes(Object[] args) 548 private void InterfaceEnableExperimentalBrushes(Object[] args)
338 { 549 {
339 if ((bool)args[0]) 550 if ((bool) args[0])
340 { 551 {
341 m_painteffects[StandardTerrainEffects.Revert] = new PaintBrushes.WeatherSphere(); 552 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere();
342 m_painteffects[StandardTerrainEffects.Flatten] = new PaintBrushes.OlsenSphere(); 553 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere();
343 m_painteffects[StandardTerrainEffects.Smooth] = new PaintBrushes.ErodeSphere(); 554 m_painteffects[StandardTerrainEffects.Smooth] = new ErodeSphere();
344 } 555 }
345 else 556 else
346 { 557 {
@@ -350,7 +561,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
350 561
351 private void InterfacePerformEffectTest(Object[] args) 562 private void InterfacePerformEffectTest(Object[] args)
352 { 563 {
353 Effects.CookieCutter cookie = new OpenSim.Region.Environment.Modules.Terrain.Effects.CookieCutter(); 564 CookieCutter cookie = new CookieCutter();
354 cookie.RunEffect(m_channel); 565 cookie.RunEffect(m_channel);
355 } 566 }
356 567
@@ -358,46 +569,69 @@ namespace OpenSim.Region.Environment.Modules.Terrain
358 { 569 {
359 // Load / Save 570 // Load / Save
360 string supportedFileExtensions = ""; 571 string supportedFileExtensions = "";
361 foreach (KeyValuePair<string,ITerrainLoader> loader in m_loaders) 572 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
362 supportedFileExtensions += " " + loader.Key + " (" + loader.Value.ToString() + ")"; 573 supportedFileExtensions += " " + loader.Key + " (" + loader.Value + ")";
363 574
364 Command loadFromFileCommand = new Command("load", InterfaceLoadFile, "Loads a terrain from a specified file."); 575 Command loadFromFileCommand =
365 loadFromFileCommand.AddArgument("filename", "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + supportedFileExtensions, "String"); 576 new Command("load", InterfaceLoadFile, "Loads a terrain from a specified file.");
366 577 loadFromFileCommand.AddArgument("filename",
367 Command saveToFileCommand = new Command("save", InterfaceSaveFile, "Saves the current heightmap to a specified file."); 578 "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " +
368 saveToFileCommand.AddArgument("filename", "The destination filename for your heightmap, the file extension determines the format to save in. Supported extensions include: " + supportedFileExtensions, "String"); 579 supportedFileExtensions, "String");
369 580
370 Command loadFromTileCommand = new Command("load-tile", InterfaceLoadTileFile, "Loads a terrain from a section of a larger file."); 581 Command saveToFileCommand =
371 loadFromTileCommand.AddArgument("filename", "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + supportedFileExtensions, "String"); 582 new Command("save", InterfaceSaveFile, "Saves the current heightmap to a specified file.");
583 saveToFileCommand.AddArgument("filename",
584 "The destination filename for your heightmap, the file extension determines the format to save in. Supported extensions include: " +
585 supportedFileExtensions, "String");
586
587 Command loadFromTileCommand =
588 new Command("load-tile", InterfaceLoadTileFile, "Loads a terrain from a section of a larger file.");
589 loadFromTileCommand.AddArgument("filename",
590 "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " +
591 supportedFileExtensions, "String");
372 loadFromTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer"); 592 loadFromTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer");
373 loadFromTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer"); 593 loadFromTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer");
374 loadFromTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file", "Integer"); 594 loadFromTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file",
375 loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file", "Integer"); 595 "Integer");
596 loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file",
597 "Integer");
376 598
377 // Terrain adjustments 599 // Terrain adjustments
378 Command fillRegionCommand = new Command("fill", InterfaceFillTerrain, "Fills the current heightmap with a specified value."); 600 Command fillRegionCommand =
379 fillRegionCommand.AddArgument("value", "The numeric value of the height you wish to set your region to.", "Double"); 601 new Command("fill", InterfaceFillTerrain, "Fills the current heightmap with a specified value.");
602 fillRegionCommand.AddArgument("value", "The numeric value of the height you wish to set your region to.",
603 "Double");
380 604
381 Command elevateCommand = new Command("elevate", InterfaceElevateTerrain, "Raises the current heightmap by the specified amount."); 605 Command elevateCommand =
606 new Command("elevate", InterfaceElevateTerrain, "Raises the current heightmap by the specified amount.");
382 elevateCommand.AddArgument("amount", "The amount of height to add to the terrain in meters.", "Double"); 607 elevateCommand.AddArgument("amount", "The amount of height to add to the terrain in meters.", "Double");
383 608
384 Command lowerCommand = new Command("lower", InterfaceLowerTerrain, "Lowers the current heightmap by the specified amount."); 609 Command lowerCommand =
610 new Command("lower", InterfaceLowerTerrain, "Lowers the current heightmap by the specified amount.");
385 lowerCommand.AddArgument("amount", "The amount of height to remove from the terrain in meters.", "Double"); 611 lowerCommand.AddArgument("amount", "The amount of height to remove from the terrain in meters.", "Double");
386 612
387 Command multiplyCommand = new Command("multiply", InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified."); 613 Command multiplyCommand =
614 new Command("multiply", InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified.");
388 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); 615 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");
389 616
390 Command bakeRegionCommand = new Command("bake", InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); 617 Command bakeRegionCommand =
391 Command revertRegionCommand = new Command("revert", InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); 618 new Command("bake", InterfaceBakeTerrain, "Saves the current terrain into the regions revert map.");
619 Command revertRegionCommand =
620 new Command("revert", InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap.");
392 621
393 // Debug 622 // Debug
394 Command showDebugStatsCommand = new Command("stats", InterfaceShowDebugStats, "Shows some information about the regions heightmap for debugging purposes."); 623 Command showDebugStatsCommand =
624 new Command("stats", InterfaceShowDebugStats,
625 "Shows some information about the regions heightmap for debugging purposes.");
395 626
396 Command experimentalBrushesCommand = new Command("newbrushes", InterfaceEnableExperimentalBrushes, "Enables experimental brushes which replace the standard terrain brushes. WARNING: This is a debug setting and may be removed at any time."); 627 Command experimentalBrushesCommand =
628 new Command("newbrushes", InterfaceEnableExperimentalBrushes,
629 "Enables experimental brushes which replace the standard terrain brushes. WARNING: This is a debug setting and may be removed at any time.");
397 experimentalBrushesCommand.AddArgument("Enabled?", "true / false - Enable new brushes", "Boolean"); 630 experimentalBrushesCommand.AddArgument("Enabled?", "true / false - Enable new brushes", "Boolean");
398 631
399 // Effects 632 // Effects
400 Command effectsTestCommand = new Command("test", InterfacePerformEffectTest, "Performs an effects module test"); 633 Command effectsTestCommand =
634 new Command("test", InterfacePerformEffectTest, "Performs an effects module test");
401 635
402 m_commander.RegisterCommand("load", loadFromFileCommand); 636 m_commander.RegisterCommand("load", loadFromFileCommand);
403 m_commander.RegisterCommand("load-tile", loadFromTileCommand); 637 m_commander.RegisterCommand("load-tile", loadFromTileCommand);
@@ -417,147 +651,5 @@ namespace OpenSim.Region.Environment.Modules.Terrain
417 } 651 }
418 652
419 #endregion 653 #endregion
420
421 void EventManager_OnPluginConsole(string[] args)
422 {
423 if (args[0] == "terrain")
424 {
425 string[] tmpArgs = new string[args.Length - 2];
426 int i = 0;
427 for (i = 2; i < args.Length; i++)
428 tmpArgs[i - 2] = args[i];
429
430 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
431 }
432 }
433
434 void EventManager_OnNewClient(IClientAPI client)
435 {
436 client.OnModifyTerrain += client_OnModifyTerrain;
437 }
438
439 void CheckForTerrainUpdates()
440 {
441 bool shouldTaint = false;
442 float[] serialised = m_channel.GetFloatsSerialised();
443 int x, y;
444 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
445 {
446 for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize)
447 {
448 if (m_channel.Tainted(x, y))
449 {
450 SendToClients(serialised, x, y);
451 shouldTaint = true;
452 }
453 }
454 }
455 if (shouldTaint)
456 {
457 m_tainted = true;
458 }
459 }
460
461 private void SendToClients(float[] serialised, int x, int y)
462 {
463 m_scene.ForEachClient(delegate(IClientAPI controller)
464 {
465 controller.SendLayerData(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
466 });
467 }
468
469 void client_OnModifyTerrain(float height, float seconds, byte size, byte action, float north, float west, float south, float east, IClientAPI remoteClient)
470 {
471 // Not a good permissions check, if in area mode, need to check the entire area.
472 if (m_scene.PermissionsMngr.CanTerraform(remoteClient.AgentId, new LLVector3(north, west, 0)))
473 {
474
475 if (north == south && east == west)
476 {
477 if (m_painteffects.ContainsKey((StandardTerrainEffects)action))
478 {
479 m_painteffects[(StandardTerrainEffects)action].PaintEffect(
480 m_channel, west, south, size, seconds);
481
482 bool usingTerrainModule = true;
483
484 if (usingTerrainModule)
485 {
486 CheckForTerrainUpdates();
487 }
488 }
489 else
490 {
491 m_log.Debug("Unknown terrain brush type " + action.ToString());
492 }
493 }
494 else
495 {
496 if (m_floodeffects.ContainsKey((StandardTerrainEffects)action))
497 {
498 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
499 fillArea.Initialize();
500
501 int x, y;
502
503 for (x = 0; x < m_channel.Width; x++)
504 {
505 for (y = 0; y < m_channel.Height; y++)
506 {
507 if (x < east && x > west)
508 {
509 if (y < north && y > south)
510 {
511 fillArea[x, y] = true;
512 }
513 }
514 }
515 }
516
517 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(
518 m_channel, fillArea, size);
519 bool usingTerrainModule = true;
520
521 if (usingTerrainModule)
522 {
523 CheckForTerrainUpdates();
524 }
525 }
526 else
527 {
528 m_log.Debug("Unknown terrain flood type " + action.ToString());
529 }
530 }
531 }
532 }
533
534 public void PostInitialise()
535 {
536 InstallDefaultEffects();
537 InstallInterfaces();
538 }
539
540 public void Close()
541 {
542 }
543
544 public string Name
545 {
546 get { return "TerrainModule"; }
547 }
548
549 public bool IsSharedModule
550 {
551 get { return false; }
552 }
553
554 #region ICommandable Members
555
556 public ICommander CommandInterface
557 {
558 get { return m_commander; }
559 }
560
561 #endregion
562 } 654 }
563} 655} \ No newline at end of file