aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World
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
parentAttempt at fixing mantis #7054. The two inventory threads are stepping on eac... (diff)
downloadopensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.zip
opensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.gz
opensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.bz2
opensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.xz
'terrain modify' command for area-of-effect operations
Signed-off-by: Michael Cerquoni <nebadon2025@gmail.com>
Diffstat (limited to 'OpenSim/Region/CoreModules/World')
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs77
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs94
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs132
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs378
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs17
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs339
10 files changed, 1266 insertions, 143 deletions
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs
new file mode 100644
index 0000000..0e0a0e4
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27
28using System;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain
32{
33 public interface ITerrainModifier
34 {
35 /// <summary>
36 /// Creates the feature.
37 /// </summary>
38 /// <returns>
39 /// Empty string if successful, otherwise error message.
40 /// </returns>
41 /// <param name='map'>
42 /// ITerrainChannel holding terrain data.
43 /// </param>
44 /// <param name='args'>
45 /// command-line arguments from console.
46 /// </param>
47 string ModifyTerrain(ITerrainChannel map, string[] args);
48
49 /// <summary>
50 /// Gets a string describing the usage.
51 /// </summary>
52 /// <returns>
53 /// A string describing parameters for creating the feature.
54 /// Format is "feature-name <arg1> <arg2> ..."
55 /// </returns>
56 string GetUsage();
57
58 /// <summary>
59 /// Apply the appropriate operation on the specified map, at (x, y).
60 /// </summary>
61 /// <param name='map'>
62 /// Map.
63 /// </param>
64 /// <param name='data'>
65 /// Data.
66 /// </param>
67 /// <param name='x'>
68 /// X.
69 /// </param>
70 /// <param name='y'>
71 /// Y.
72 /// </param>
73 double operate(double[,] map, TerrainModifierData data, int x, int y);
74 }
75
76}
77
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs
new file mode 100644
index 0000000..0df7132
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs
@@ -0,0 +1,94 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27using System;
28
29using OpenSim.Region.CoreModules.World.Terrain;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
33{
34 public class FillModifier : TerrainModifier
35 {
36
37 public FillModifier(ITerrainModule module) : base(module)
38 {
39 }
40
41 public override string ModifyTerrain(ITerrainChannel map, string[] args)
42 {
43 string val;
44 string result;
45 if (args.Length < 3)
46 {
47 result = "Usage: " + GetUsage();
48 }
49 else
50 {
51 TerrainModifierData data;
52 result = this.parseParameters(args, out data);
53
54 // Context-specific validation
55 if (result == String.Empty)
56 {
57 if (data.shape == String.Empty)
58 {
59 data.shape = "rectangle";
60 data.x0 = 0;
61 data.y0 = 0;
62 data.dx = map.Width;
63 data.dy = map.Height;
64 }
65 }
66
67 // if it's all good, then do the work
68 if (result == String.Empty)
69 {
70 this.applyModification(map, data);
71 }
72 }
73
74 return result;
75 }
76
77 public override string GetUsage()
78 {
79 string val = "fill <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
80 + "\nSets all points within the specified range to the specified value.";
81 return val;
82 }
83
84 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
85 {
86 double factor = this.computeBevel(data, x, y);
87 double result = data.elevation - (data.elevation - data.bevelevation) * factor;
88 return result;
89 }
90
91 }
92
93}
94
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs
new file mode 100644
index 0000000..3e4a457
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs
@@ -0,0 +1,93 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class LowerModifier : TerrainModifier
34 {
35 public LowerModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "lower <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
78 + "\nLowers all points within the specified range by the specified amount.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = map[x, y] - (data.elevation - (data.elevation - data.bevelevation) * factor);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs
new file mode 100644
index 0000000..02f1852
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs
@@ -0,0 +1,93 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class MaxModifier : TerrainModifier
34 {
35 public MaxModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "max <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
78 + "\nEnsures that all points within the specified range are no higher than the specified value.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = Math.Min(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs
new file mode 100644
index 0000000..2db49c8
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs
@@ -0,0 +1,93 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class MinModifier : TerrainModifier
34 {
35 public MinModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "min <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
78 + "\nEnsures that all points within the specified range are no lower than the specified value.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = Math.Max(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs
new file mode 100644
index 0000000..9ac1edd
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs
@@ -0,0 +1,93 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class RaiseModifier : TerrainModifier
34 {
35 public RaiseModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "raise <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
78 + "\nRaises all points within the specified range by the specified amount.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs
new file mode 100644
index 0000000..1731cd8
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs
@@ -0,0 +1,132 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class SmoothModifier : TerrainModifier
34 {
35 public SmoothModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.bevel == "taper")
56 {
57 if (data.bevelevation < 0.01 || data.bevelevation > 0.99)
58 {
59 result = String.Format("Taper must be 0.01 to 0.99 {0}", data.bevelevation);
60 }
61 }
62 else
63 {
64 data.bevelevation = 2.0f / 3.0f;
65 }
66
67 if (data.elevation < 0.0 || data.elevation > 1.0)
68 {
69 result = String.Format("Scaling factor must be 0.0 to 1.0: {0}", data.elevation);
70 }
71
72 if (data.shape == String.Empty)
73 {
74 data.shape = "rectangle";
75 data.x0 = 0;
76 data.y0 = 0;
77 data.dx = map.Width;
78 data.dy = map.Height;
79 }
80 }
81
82 // if it's all good, then do the work
83 if (result == String.Empty)
84 {
85 this.applyModification(map, data);
86 }
87 }
88
89 return result;
90 }
91
92 public override string GetUsage()
93 {
94 string val = "smooth <strength> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<fraction>]"
95 + "\nSmooths all points within the specified range using a simple averaging algorithm.";
96 return val;
97 }
98
99 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
100 {
101 double[] scale = new double[3];
102 scale[0] = data.elevation;
103 scale[1] = ((1.0 - scale[0]) * data.bevelevation) / 8.0;
104 scale[2] = ((1.0 - scale[0]) * (1.0 - data.bevelevation)) / 16.0;
105 int xMax = map.GetLength(0);
106 int yMax = map.GetLength(1);
107 double result;
108 if ((x == 0) || (y == 0) || (x == (xMax - 1)) || (y == (yMax - 1)))
109 {
110 result = map[x, y];
111 }
112 else
113 {
114 result = 0.0;
115 for(int yPos = (y - 2); yPos < (y + 3); yPos++)
116 {
117 int yVal = (yPos <= 0) ? 0 : ((yPos < yMax) ? yPos : yMax - 1);
118 for(int xPos = (x - 2); xPos < (x + 3); xPos++)
119 {
120 int xVal = (xPos <= 0) ? 0 : ((xPos < xMax) ? xPos : xMax - 1);
121 int dist = Math.Max(Math.Abs(x - xVal), Math.Abs(y - yVal));
122 result += map[xVal, yVal] * scale[dist];
123 }
124 }
125 }
126 return result;
127 }
128
129 }
130
131}
132
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
new file mode 100644
index 0000000..7ebd08e
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
@@ -0,0 +1,378 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27using System;
28using System.Reflection;
29using log4net;
30
31using OpenSim.Region.Framework.Interfaces;
32
33namespace OpenSim.Region.CoreModules.World.Terrain
34{
35 public abstract class TerrainModifier : ITerrainModifier
36 {
37 protected ITerrainModule m_module;
38 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 protected TerrainModifier(ITerrainModule module)
41 {
42 m_module = module;
43 }
44
45 public abstract string ModifyTerrain(ITerrainChannel map, string[] args);
46
47 public abstract string GetUsage();
48
49 public abstract double operate(double[,] map, TerrainModifierData data, int x, int y);
50
51 protected String parseParameters(string[] args, out TerrainModifierData data)
52 {
53 string val;
54 string arg;
55 string result;
56 data = new TerrainModifierData();
57 data.shape = String.Empty;
58 data.bevel = String.Empty;
59 data.dx = 0;
60 data.dy = 0;
61 if (args.Length < 4)
62 {
63 result = "Usage: " + GetUsage();
64 }
65 else
66 {
67 result = this.parseFloat(args[3], out data.elevation);
68 }
69 if (result == String.Empty)
70 {
71 int index = 3;
72 while(++index < args.Length && result == String.Empty)
73 {
74 arg = args[index];
75 // check for shape
76 if (arg.StartsWith("-rec=") || arg.StartsWith("-ell="))
77 {
78 if (data.shape != String.Empty)
79 {
80 result = "Only 1 '-rec' or '-ell' parameter is permitted.";
81 }
82 else
83 {
84 data.shape = arg.StartsWith("-ell=") ? "ellipse" : "rectangle";
85 val = arg.Substring(arg.IndexOf("=") + 1);
86 string[] coords = val.Split(new char[] {','});
87 if ((coords.Length < 3) || (coords.Length > 4))
88 {
89 result = String.Format("Bad format for shape parameter {0}", arg);
90 }
91 else
92 {
93 result = this.parseInt(coords[0], out data.x0);
94 if (result == String.Empty)
95 {
96 result = this.parseInt(coords[1], out data.y0);
97 }
98 if (result == String.Empty)
99 {
100 result = this.parseInt(coords[2], out data.dx);
101 }
102 if (result == String.Empty)
103 {
104 if (coords.Length == 4)
105 {
106 result = this.parseInt(coords[3], out data.dy);
107 }
108 else
109 {
110 data.dy = data.dx;
111 }
112 }
113 if (result == String.Empty)
114 {
115 if ((data.dx <= 0) || (data.dy <= 0))
116 {
117 result = "Shape sizes must be positive integers";
118 }
119 }
120 else
121 {
122 result = String.Format("Bad value in shape parameters {0}", arg);
123 }
124 }
125 }
126 }
127 else if (arg.StartsWith("-taper="))
128 {
129 if (data.bevel != String.Empty)
130 {
131 result = "Only 1 '-taper' parameter is permitted.";
132 }
133 else
134 {
135 data.bevel = "taper";
136 val = arg.Substring(arg.IndexOf("=") + 1);
137 result = this.parseFloat(val, out data.bevelevation);
138 if (result != String.Empty)
139 {
140 result = String.Format("Bad format for taper parameter {0}", arg);
141 }
142 }
143 }
144 else
145 {
146 result = String.Format("Unrecognized parameter {0}", arg);
147 }
148 }
149 }
150 return result;
151 }
152
153 protected string parseFloat(String s, out float f)
154 {
155 string result;
156 double d;
157 if (Double.TryParse(s, out d))
158 {
159 try
160 {
161 f = (float)d;
162 result = String.Empty;
163 }
164 catch(InvalidCastException)
165 {
166 result = String.Format("{0} is invalid", s);
167 f = -1.0f;
168 }
169 }
170 else
171 {
172 f = -1.0f;
173 result = String.Format("{0} is invalid", s);
174 }
175 return result;
176 }
177
178 protected string parseInt(String s, out int i)
179 {
180 string result;
181 if (Int32.TryParse(s, out i))
182 {
183 result = String.Empty;
184 }
185 else
186 {
187 result = String.Format("{0} is invalid", s);
188 }
189 return result;
190 }
191
192 protected void applyModification(ITerrainChannel map, TerrainModifierData data)
193 {
194 bool[,] mask;
195 int xMax;
196 int yMax;
197 int xMid;
198 int yMid;
199 if (data.shape == "ellipse")
200 {
201 mask = this.ellipticalMask(data.dx, data.dy);
202 xMax = mask.GetLength(0);
203 yMax = mask.GetLength(1);
204 xMid = xMax / 2 + xMax % 2;
205 yMid = yMax / 2 + yMax % 2;
206 }
207 else
208 {
209 mask = this.rectangularMask(data.dx, data.dy);
210 xMax = mask.GetLength(0);
211 yMax = mask.GetLength(1);
212 xMid = 0;
213 yMid = 0;
214 }
215// m_log.DebugFormat("Apply {0} mask {1}x{2} @ {3},{4}", data.shape, xMax, yMax, xMid, yMid);
216 double[,] buffer = map.GetDoubles();
217 int yDim = yMax;
218 while(--yDim >= 0)
219 {
220 int yPos = data.y0 + yDim - yMid;
221 if ((yPos >= 0) && (yPos < map.Height))
222 {
223 int xDim = xMax;
224 while(--xDim >= 0)
225 {
226 int xPos = data.x0 + xDim - xMid;
227 if ((xPos >= 0) && (xPos < map.Width) && (mask[xDim, yDim]))
228 {
229 double endElevation = this.operate(buffer, data, xPos, yPos);
230 map[xPos, yPos] = endElevation;
231 }
232 }
233 }
234 }
235 }
236
237 protected double computeBevel(TerrainModifierData data, int x, int y)
238 {
239 int deltaX;
240 int deltaY;
241 int xMax;
242 int yMax;
243 double factor;
244 if (data.bevel == "taper")
245 {
246 if (data.shape == "ellipse")
247 {
248 deltaX = x - data.x0;
249 deltaY = y - data.y0;
250 xMax = data.dx;
251 yMax = data.dy;
252 factor = (double)((deltaX * deltaX) + (deltaY * deltaY));
253 factor /= ((xMax * xMax) + (yMax * yMax));
254 }
255 else
256 {
257 // pyramid
258 xMax = data.dx / 2 + data.dx % 2;
259 yMax = data.dy / 2 + data.dy % 2;
260 deltaX = Math.Abs(data.x0 + xMax - x);
261 deltaY = Math.Abs(data.y0 + yMax - y);
262 factor = Math.Max(((double)(deltaY) / yMax), ((double)(deltaX) / xMax));
263 }
264 }
265 else
266 {
267 factor = 0.0;
268 }
269 return factor;
270 }
271
272 private bool[,] rectangularMask(int xSize, int ySize)
273 {
274 bool[,] mask = new bool[xSize, ySize];
275 int yPos = ySize;
276 while(--yPos >= 0)
277 {
278 int xPos = xSize;
279 while(--xPos >= 0)
280 {
281 mask[xPos, yPos] = true;
282 }
283 }
284 return mask;
285 }
286
287 /*
288 * Fast ellipse-based derivative of Bresenham algorithm.
289 * https://web.archive.org/web/20120225095359/http://homepage.smc.edu/kennedy_john/belipse.pdf
290 */
291 private bool[,] ellipticalMask(int xRadius, int yRadius)
292 {
293 long twoASquared = 2L * xRadius * xRadius;
294 long twoBSquared = 2L * yRadius * yRadius;
295
296 bool[,] mask = new bool[2 * xRadius + 1, 2 * yRadius + 1];
297
298 long ellipseError = 0L;
299 long stoppingX = twoBSquared * xRadius;
300 long stoppingY = 0L;
301 long xChange = yRadius * yRadius * (1L - 2L * xRadius);
302 long yChange = xRadius * xRadius;
303
304 int xPos = xRadius;
305 int yPos = 0;
306
307 // first set of points
308 while(stoppingX >= stoppingY)
309 {
310 int yUpper = yRadius + yPos;
311 int yLower = yRadius - yPos;
312 // fill in the mask
313 int xNow = xPos;
314 while(xNow >= 0)
315 {
316 mask[xRadius + xNow, yUpper] = true;
317 mask[xRadius - xNow, yUpper] = true;
318 mask[xRadius + xNow, yLower] = true;
319 mask[xRadius - xNow, yLower] = true;
320 --xNow;
321 }
322 yPos++;
323 stoppingY += twoASquared;
324 ellipseError += yChange;
325 yChange += twoASquared;
326 if ((2L * ellipseError + xChange) > 0L)
327 {
328 xPos--;
329 stoppingX -= twoBSquared;
330 ellipseError += xChange;
331 xChange += twoBSquared;
332 }
333 }
334
335 // second set of points
336 xPos = 0;
337 yPos = yRadius;
338 xChange = yRadius * yRadius;
339 yChange = xRadius * xRadius * (1L - 2L * yRadius);
340
341 ellipseError = 0L;
342 stoppingX = 0L;
343 stoppingY = twoASquared * yRadius;
344
345 while(stoppingX <= stoppingY)
346 {
347 int xUpper = xRadius + xPos;
348 int xLower = xRadius - xPos;
349 // fill in the mask
350 int yNow = yPos;
351 while(yNow >= 0)
352 {
353 mask[xUpper, yRadius + yNow] = true;
354 mask[xUpper, yRadius - yNow] = true;
355 mask[xLower, yRadius + yNow] = true;
356 mask[xLower, yRadius - yNow] = true;
357 --yNow;
358 }
359 xPos++;
360 stoppingX += twoBSquared;
361 ellipseError += xChange;
362 xChange += twoBSquared;
363 if ((2L * ellipseError + yChange) > 0L)
364 {
365 yPos--;
366 stoppingY -= twoASquared;
367 ellipseError += yChange;
368 yChange += twoASquared;
369 }
370 }
371 return mask;
372 }
373
374
375 }
376
377}
378
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs
new file mode 100644
index 0000000..4e0f8d7
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs
@@ -0,0 +1,17 @@
1using System;
2
3namespace OpenSim.Region.CoreModules.World.Terrain
4{
5 public struct TerrainModifierData
6 {
7 public float elevation;
8 public string shape;
9 public int x0;
10 public int y0;
11 public int dx;
12 public int dy;
13 public string bevel;
14 public float bevelevation;
15 }
16}
17
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}