aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World
diff options
context:
space:
mode:
authorMichael Heilmann2015-05-19 15:18:45 -0400
committerMichael Heilmann2015-05-19 15:18:45 -0400
commit140ea04b9d692344d803fc87364fb252561725c3 (patch)
treed503b7ae17baca374d704b548fc7da512f512388 /OpenSim/Region/CoreModules/World
parentMerge pull request #7 from gamucf/moses.metricsPhase2 (diff)
parentresolve possible nullref when sending appearance packet. Thanks to zadark for... (diff)
downloadopensim-SC_OLD-140ea04b9d692344d803fc87364fb252561725c3.zip
opensim-SC_OLD-140ea04b9d692344d803fc87364fb252561725c3.tar.gz
opensim-SC_OLD-140ea04b9d692344d803fc87364fb252561725c3.tar.bz2
opensim-SC_OLD-140ea04b9d692344d803fc87364fb252561725c3.tar.xz
Merging Opensim upstream before generating patch
Diffstat (limited to 'OpenSim/Region/CoreModules/World')
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs84
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs149
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs (renamed from OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs)90
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs108
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs131
-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.cs366
14 files changed, 1403 insertions, 383 deletions
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 4d99a6e..db66c83 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -335,7 +335,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
335 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) 335 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
336 { 336 {
337 //m_log.DebugFormat("[ARCHIVER]: Rewriting object data for {0}", asset.ID); 337 //m_log.DebugFormat("[ARCHIVER]: Rewriting object data for {0}", asset.ID);
338 string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), m_options["home"].ToString(), m_userAccountService, m_scopeID); 338 string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), string.Empty, m_options["home"].ToString(), m_userAccountService, m_scopeID);
339 asset.Data = Utils.StringToBytes(xml); 339 asset.Data = Utils.StringToBytes(xml);
340 } 340 }
341 return asset; 341 return asset;
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 13485bf..25e1454 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -98,11 +98,17 @@ namespace OpenSim.Region.CoreModules.World.Land
98 // caches ExtendedLandData 98 // caches ExtendedLandData
99 private Cache parcelInfoCache; 99 private Cache parcelInfoCache;
100 100
101
101 /// <summary> 102 /// <summary>
102 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. 103 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
103 /// </summary> 104 /// </summary>
104 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>(); 105 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>();
105 106
107 // Enables limiting parcel layer info transmission when doing simple updates
108 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; }
109 // "View distance" for sending parcel layer info if asked for from a view point in the region
110 private int parcelLayerViewDistance { get; set; }
111
106 #region INonSharedRegionModule Members 112 #region INonSharedRegionModule Members
107 113
108 public Type ReplaceableInterface 114 public Type ReplaceableInterface
@@ -112,6 +118,14 @@ namespace OpenSim.Region.CoreModules.World.Land
112 118
113 public void Initialise(IConfigSource source) 119 public void Initialise(IConfigSource source)
114 { 120 {
121 shouldLimitParcelLayerInfoToViewDistance = true;
122 parcelLayerViewDistance = 128;
123 IConfig landManagementConfig = source.Configs["LandManagement"];
124 if (landManagementConfig != null)
125 {
126 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance);
127 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance);
128 }
115 } 129 }
116 130
117 public void AddRegion(Scene scene) 131 public void AddRegion(Scene scene)
@@ -1129,11 +1143,26 @@ namespace OpenSim.Region.CoreModules.World.Land
1129 1143
1130 #region Parcel Updating 1144 #region Parcel Updating
1131 1145
1146 // Send parcel layer info for the whole region
1147 public void SendParcelOverlay(IClientAPI remote_client)
1148 {
1149 SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize);
1150 }
1151
1132 /// <summary> 1152 /// <summary>
1133 /// Where we send the ParcelOverlay packet to the client 1153 /// Send the parcel overlay blocks to the client. We send the overlay packets
1154 /// around a location and limited by the 'parcelLayerViewDistance'. This number
1155 /// is usually 128 and the code is arranged so it sends all the parcel overlay
1156 /// information for a whole region if the region is legacy sized (256x256). If
1157 /// the region is larger, only the parcel layer information is sent around
1158 /// the point specified. This reduces the problem of parcel layer information
1159 /// blocks increasing exponentially as region size increases.
1134 /// </summary> 1160 /// </summary>
1135 /// <param name="remote_client">The object representing the client</param> 1161 /// <param name="remote_client">The object representing the client</param>
1136 public void SendParcelOverlay(IClientAPI remote_client) 1162 /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param>
1163 /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param>
1164 /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param>
1165 private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance)
1137 { 1166 {
1138 const int LAND_BLOCKS_PER_PACKET = 1024; 1167 const int LAND_BLOCKS_PER_PACKET = 1024;
1139 1168
@@ -1141,15 +1170,58 @@ namespace OpenSim.Region.CoreModules.World.Land
1141 int byteArrayCount = 0; 1170 int byteArrayCount = 0;
1142 int sequenceID = 0; 1171 int sequenceID = 0;
1143 1172
1173 int xLow = 0;
1174 int xHigh = (int)m_scene.RegionInfo.RegionSizeX;
1175 int yLow = 0;
1176 int yHigh = (int)m_scene.RegionInfo.RegionSizeY;
1177
1178 if (shouldLimitParcelLayerInfoToViewDistance)
1179 {
1180 // Compute view distance around the given point
1181 int txLow = xPlace - layerViewDistance;
1182 int txHigh = xPlace + layerViewDistance;
1183 // If the distance is outside the region area, move the view distance to ba all in the region
1184 if (txLow < xLow)
1185 {
1186 txLow = xLow;
1187 txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh);
1188 }
1189 if (txHigh > xHigh)
1190 {
1191 txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2));
1192 txHigh = xHigh;
1193 }
1194 xLow = txLow;
1195 xHigh = txHigh;
1196
1197 int tyLow = yPlace - layerViewDistance;
1198 int tyHigh = yPlace + layerViewDistance;
1199 if (tyLow < yLow)
1200 {
1201 tyLow = yLow;
1202 tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh);
1203 }
1204 if (tyHigh > yHigh)
1205 {
1206 tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2));
1207 tyHigh = yHigh;
1208 }
1209 yLow = tyLow;
1210 yHigh = tyHigh;
1211 }
1212 // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>",
1213 // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh);
1214
1144 // Layer data is in landUnit (4m) chunks 1215 // Layer data is in landUnit (4m) chunks
1145 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) 1216 for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1146 { 1217 {
1147 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) 1218 for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
1148 { 1219 {
1149 byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client); 1220 byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client);
1150 byteArrayCount++; 1221 byteArrayCount++;
1151 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) 1222 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1152 { 1223 {
1224 // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length);
1153 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1225 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1154 byteArrayCount = 0; 1226 byteArrayCount = 0;
1155 sequenceID++; 1227 sequenceID++;
@@ -1162,6 +1234,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1162 if (byteArrayCount != 0) 1234 if (byteArrayCount != 0)
1163 { 1235 {
1164 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1236 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1237 // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length);
1165 } 1238 }
1166 } 1239 }
1167 1240
@@ -1265,7 +1338,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1265 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); 1338 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
1266 } 1339 }
1267 1340
1268 SendParcelOverlay(remote_client); 1341 // Also send the layer data around the point of interest
1342 SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance);
1269 } 1343 }
1270 1344
1271 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) 1345 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs b/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs
deleted file mode 100644
index 33c3fbe..0000000
--- a/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs
+++ /dev/null
@@ -1,149 +0,0 @@
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.CoreModules.World.Terrain;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.World.Terrain.Features
33{
34 public class RectangleFeature : TerrainFeature
35 {
36 public RectangleFeature(ITerrainModule module) : base(module)
37 {
38 }
39
40 public override string CreateFeature(ITerrainChannel map, string[] args)
41 {
42 string val;
43 string result;
44 if (args.Length < 7)
45 {
46 result = "Usage: " + GetUsage();
47 }
48 else
49 {
50 result = String.Empty;
51
52 float targetElevation;
53 val = base.parseFloat(args[3], out targetElevation);
54 if (val != String.Empty)
55 {
56 result = val;
57 }
58
59 int xOrigin;
60 val = base.parseInt(args[4], out xOrigin);
61 if (val != String.Empty)
62 {
63 result = val;
64 }
65 else if (xOrigin < 0 || xOrigin >= map.Width)
66 {
67 result = "x-origin must be within the region";
68 }
69
70 int yOrigin;
71 val = base.parseInt(args[5], out yOrigin);
72 if (val != String.Empty)
73 {
74 result = val;
75 }
76 else if (yOrigin < 0 || yOrigin >= map.Height)
77 {
78 result = "y-origin must be within the region";
79 }
80
81 int xDelta;
82 val = base.parseInt(args[6], out xDelta);
83 if (val != String.Empty)
84 {
85 result = val;
86 }
87 else if (xDelta <= 0)
88 {
89 result = "x-size must be greater than zero";
90 }
91
92 int yDelta;
93 if (args.Length > 7)
94 {
95 val = base.parseInt(args[7], out yDelta);
96 if (val != String.Empty)
97 {
98 result = val;
99 }
100 else if (yDelta <= 0)
101 {
102 result = "y-size must be greater than zero";
103 }
104 }
105 else
106 {
107 // no y-size.. make it square
108 yDelta = xDelta;
109 }
110
111 // slightly more complex validation, if required.
112 if (result == String.Empty)
113 {
114 if (xOrigin + xDelta > map.Width)
115 {
116 result = "(x-origin + x-size) must be within the region size";
117 }
118 else if (yOrigin + yDelta > map.Height)
119 {
120 result = "(y-origin + y-size) must be within the region size";
121 }
122 }
123
124 // if it's all good, then do the work
125 if (result == String.Empty)
126 {
127 int yPos = yOrigin + yDelta;
128 while(--yPos >= yOrigin)
129 {
130 int xPos = xOrigin + xDelta;
131 while(--xPos >= xOrigin)
132 {
133 map[xPos, yPos] = (double)targetElevation;
134 }
135 }
136 }
137 }
138
139 return result;
140 }
141
142 public override string GetUsage()
143 {
144 return "rectangle <height> <x-origin> <y-origin> <x-size> [<y-size>]";
145 }
146 }
147
148}
149
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs
index 701a729..0e0a0e4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs
@@ -24,65 +24,53 @@
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 */
27using System;
28using System.Reflection;
29 27
28using System;
30using OpenSim.Region.Framework.Interfaces; 29using OpenSim.Region.Framework.Interfaces;
31 30
32namespace OpenSim.Region.CoreModules.World.Terrain 31namespace OpenSim.Region.CoreModules.World.Terrain
33{ 32{
34 public abstract class TerrainFeature : ITerrainFeature 33 public interface ITerrainModifier
35 { 34 {
36 protected ITerrainModule m_module; 35 /// <summary>
37 36 /// Creates the feature.
38 protected TerrainFeature(ITerrainModule module) 37 /// </summary>
39 { 38 /// <returns>
40 m_module = module; 39 /// Empty string if successful, otherwise error message.
41 } 40 /// </returns>
42 41 /// <param name='map'>
43 public abstract string CreateFeature(ITerrainChannel map, string[] args); 42 /// ITerrainChannel holding terrain data.
44 43 /// </param>
45 public abstract string GetUsage(); 44 /// <param name='args'>
46 45 /// command-line arguments from console.
47 protected string parseFloat(String s, out float f) 46 /// </param>
48 { 47 string ModifyTerrain(ITerrainChannel map, string[] args);
49 string result;
50 double d;
51 if (Double.TryParse(s, out d))
52 {
53 try
54 {
55 f = (float)d;
56 result = String.Empty;
57 }
58 catch(InvalidCastException)
59 {
60 result = String.Format("{0} is invalid", s);
61 f = -1.0f;
62 }
63 }
64 else
65 {
66 f = -1.0f;
67 result = String.Format("{0} is invalid", s);
68 }
69 return result;
70 }
71 48
72 protected string parseInt(String s, out int i) 49 /// <summary>
73 { 50 /// Gets a string describing the usage.
74 string result; 51 /// </summary>
75 if (Int32.TryParse(s, out i)) 52 /// <returns>
76 { 53 /// A string describing parameters for creating the feature.
77 result = String.Empty; 54 /// Format is "feature-name <arg1> <arg2> ..."
78 } 55 /// </returns>
79 else 56 string GetUsage();
80 {
81 result = String.Format("{0} is invalid", s);
82 }
83 return result;
84 }
85 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);
86 } 74 }
87 75
88} 76}
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..32f1de9
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.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;
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 result;
44 if (args.Length < 3)
45 {
46 result = "Usage: " + GetUsage();
47 }
48 else
49 {
50 TerrainModifierData data;
51 result = this.parseParameters(args, out data);
52
53 // Context-specific validation
54 if (result == String.Empty)
55 {
56 if (data.shape == String.Empty)
57 {
58 data.shape = "rectangle";
59 data.x0 = 0;
60 data.y0 = 0;
61 data.dx = map.Width;
62 data.dy = map.Height;
63 }
64 }
65
66 // if it's all good, then do the work
67 if (result == String.Empty)
68 {
69 this.applyModification(map, data);
70 }
71 }
72
73 return result;
74 }
75
76 public override string GetUsage()
77 {
78 string val = "fill <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
79 + "\nSets all points within the specified range to the specified value.";
80 return val;
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 = 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/LowerModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs
new file mode 100644
index 0000000..2ab4bcc
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs
@@ -0,0 +1,92 @@
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 result;
42 if (args.Length < 3)
43 {
44 result = "Usage: " + GetUsage();
45 }
46 else
47 {
48 TerrainModifierData data;
49 result = this.parseParameters(args, out data);
50
51 // Context-specific validation
52 if (result == String.Empty)
53 {
54 if (data.shape == String.Empty)
55 {
56 data.shape = "rectangle";
57 data.x0 = 0;
58 data.y0 = 0;
59 data.dx = map.Width;
60 data.dy = map.Height;
61 }
62 }
63
64 // if it's all good, then do the work
65 if (result == String.Empty)
66 {
67 this.applyModification(map, data);
68 }
69 }
70
71 return result;
72 }
73
74 public override string GetUsage()
75 {
76 string val = "lower <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
77 + "\nLowers all points within the specified range by the specified amount.";
78 return val;
79
80 }
81
82 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
83 {
84 double factor = this.computeBevel(data, x, y);
85 double result = map[x, y] - (data.elevation - (data.elevation - data.bevelevation) * factor);
86 return result;
87 }
88
89 }
90
91}
92
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..0939c0a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs
@@ -0,0 +1,92 @@
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 result;
42 if (args.Length < 3)
43 {
44 result = "Usage: " + GetUsage();
45 }
46 else
47 {
48 TerrainModifierData data;
49 result = this.parseParameters(args, out data);
50
51 // Context-specific validation
52 if (result == String.Empty)
53 {
54 if (data.shape == String.Empty)
55 {
56 data.shape = "rectangle";
57 data.x0 = 0;
58 data.y0 = 0;
59 data.dx = map.Width;
60 data.dy = map.Height;
61 }
62 }
63
64 // if it's all good, then do the work
65 if (result == String.Empty)
66 {
67 this.applyModification(map, data);
68 }
69 }
70
71 return result;
72 }
73
74 public override string GetUsage()
75 {
76 string val = "max <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
77 + "\nEnsures that all points within the specified range are no higher than the specified value.";
78 return val;
79
80 }
81
82 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
83 {
84 double factor = this.computeBevel(data, x, y);
85 double result = Math.Min(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
86 return result;
87 }
88
89 }
90
91}
92
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..cbbccc0
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs
@@ -0,0 +1,92 @@
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 result;
42 if (args.Length < 3)
43 {
44 result = "Usage: " + GetUsage();
45 }
46 else
47 {
48 TerrainModifierData data;
49 result = this.parseParameters(args, out data);
50
51 // Context-specific validation
52 if (result == String.Empty)
53 {
54 if (data.shape == String.Empty)
55 {
56 data.shape = "rectangle";
57 data.x0 = 0;
58 data.y0 = 0;
59 data.dx = map.Width;
60 data.dy = map.Height;
61 }
62 }
63
64 // if it's all good, then do the work
65 if (result == String.Empty)
66 {
67 this.applyModification(map, data);
68 }
69 }
70
71 return result;
72 }
73
74 public override string GetUsage()
75 {
76 string val = "min <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
77 + "\nEnsures that all points within the specified range are no lower than the specified value.";
78 return val;
79
80 }
81
82 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
83 {
84 double factor = this.computeBevel(data, x, y);
85 double result = Math.Max(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
86 return result;
87 }
88
89 }
90
91}
92
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs
new file mode 100644
index 0000000..d6b95d0
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs
@@ -0,0 +1,108 @@
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;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
33{
34 public class NoiseModifier : TerrainModifier
35 {
36 public NoiseModifier(ITerrainModule module) : base(module)
37 {
38 }
39
40 public override string ModifyTerrain(ITerrainChannel map, string[] args)
41 {
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.0 || data.bevelevation > 1.0)
58 {
59 result = String.Format("Taper must be 0.0 to 1.0: {0}", data.bevelevation);
60 }
61 }
62 else
63 {
64 data.bevelevation = 1.0f;
65 }
66
67 if (data.elevation < 0.0 || data.elevation > 1.0)
68 {
69 result = String.Format("Noise strength 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 = "noise <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
95 + "\nAdds noise to all points within the specified range.";
96 return val;
97 }
98
99 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
100 {
101 double factor = this.computeBevel(data, x, y);
102 double noise = TerrainUtil.PerlinNoise2D((double)x / map.GetLength(0), (double)y / map.GetLength(1), 8, 1.0);
103 return map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor) * (noise - .5);
104 }
105
106 }
107
108}
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..35fb9d6
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs
@@ -0,0 +1,92 @@
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 result;
42 if (args.Length < 3)
43 {
44 result = "Usage: " + GetUsage();
45 }
46 else
47 {
48 TerrainModifierData data;
49 result = this.parseParameters(args, out data);
50
51 // Context-specific validation
52 if (result == String.Empty)
53 {
54 if (data.shape == String.Empty)
55 {
56 data.shape = "rectangle";
57 data.x0 = 0;
58 data.y0 = 0;
59 data.dx = map.Width;
60 data.dy = map.Height;
61 }
62 }
63
64 // if it's all good, then do the work
65 if (result == String.Empty)
66 {
67 this.applyModification(map, data);
68 }
69 }
70
71 return result;
72 }
73
74 public override string GetUsage()
75 {
76 string val = "raise <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
77 + "\nRaises all points within the specified range by the specified amount.";
78 return val;
79
80 }
81
82 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
83 {
84 double factor = this.computeBevel(data, x, y);
85 double result = map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor);
86 return result;
87 }
88
89 }
90
91}
92
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..9f8d5b2
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs
@@ -0,0 +1,131 @@
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 result;
42 if (args.Length < 3)
43 {
44 result = "Usage: " + GetUsage();
45 }
46 else
47 {
48 TerrainModifierData data;
49 result = this.parseParameters(args, out data);
50
51 // Context-specific validation
52 if (result == String.Empty)
53 {
54 if (data.bevel == "taper")
55 {
56 if (data.bevelevation < 0.01 || data.bevelevation > 0.99)
57 {
58 result = String.Format("Taper must be 0.01 to 0.99: {0}", data.bevelevation);
59 }
60 }
61 else
62 {
63 data.bevelevation = 2.0f / 3.0f;
64 }
65
66 if (data.elevation < 0.0 || data.elevation > 1.0)
67 {
68 result = String.Format("Smoothing strength must be 0.0 to 1.0: {0}", data.elevation);
69 }
70
71 if (data.shape == String.Empty)
72 {
73 data.shape = "rectangle";
74 data.x0 = 0;
75 data.y0 = 0;
76 data.dx = map.Width;
77 data.dy = map.Height;
78 }
79 }
80
81 // if it's all good, then do the work
82 if (result == String.Empty)
83 {
84 this.applyModification(map, data);
85 }
86 }
87
88 return result;
89 }
90
91 public override string GetUsage()
92 {
93 string val = "smooth <strength> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<fraction>]"
94 + "\nSmooths all points within the specified range using a simple averaging algorithm.";
95 return val;
96 }
97
98 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
99 {
100 double[] scale = new double[3];
101 scale[0] = data.elevation;
102 scale[1] = ((1.0 - scale[0]) * data.bevelevation) / 8.0;
103 scale[2] = ((1.0 - scale[0]) * (1.0 - data.bevelevation)) / 16.0;
104 int xMax = map.GetLength(0);
105 int yMax = map.GetLength(1);
106 double result;
107 if ((x == 0) || (y == 0) || (x == (xMax - 1)) || (y == (yMax - 1)))
108 {
109 result = map[x, y];
110 }
111 else
112 {
113 result = 0.0;
114 for(int yPos = (y - 2); yPos < (y + 3); yPos++)
115 {
116 int yVal = (yPos <= 0) ? 0 : ((yPos < yMax) ? yPos : yMax - 1);
117 for(int xPos = (x - 2); xPos < (x + 3); xPos++)
118 {
119 int xVal = (xPos <= 0) ? 0 : ((xPos < xMax) ? xPos : xMax - 1);
120 int dist = Math.Max(Math.Abs(x - xVal), Math.Abs(y - yVal));
121 result += map[xVal, yVal] * scale[dist];
122 }
123 }
124 }
125 return result;
126 }
127
128 }
129
130}
131
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..cec17e2 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;
@@ -42,7 +41,7 @@ using OpenSim.Framework;
42using OpenSim.Framework.Console; 41using 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.Modifiers;
46using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; 45using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes;
47using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; 46using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
48using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
@@ -75,14 +74,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
75 74
76 #endregion 75 #endregion
77 76
78 /// <summary>
79 /// Terrain Features
80 /// </summary>
81 public enum TerrainFeatures: byte
82 {
83 Rectangle = 1,
84 }
85
86 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
87 78
88#pragma warning disable 414 79#pragma warning disable 414
@@ -90,26 +81,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
90#pragma warning restore 414 81#pragma warning restore 414
91 82
92 private readonly Commander m_commander = new Commander("terrain"); 83 private readonly Commander m_commander = new Commander("terrain");
93
94 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects = 84 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
95 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>(); 85 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
96
97 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); 86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
98
99 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
100 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
101
102 private Dictionary<string, ITerrainEffect> m_plugineffects; 89 private Dictionary<string, ITerrainEffect> m_plugineffects;
103 90 private Dictionary<string, ITerrainModifier> m_modifyOperations =
104 private Dictionary<string, ITerrainFeature> m_featureEffects = 91 new Dictionary<string, ITerrainModifier>();
105 new Dictionary<string, ITerrainFeature>();
106
107 private ITerrainChannel m_channel; 92 private ITerrainChannel m_channel;
108 private ITerrainChannel m_revert; 93 private ITerrainChannel m_revert;
109 private Scene m_scene; 94 private Scene m_scene;
110 private volatile bool m_tainted; 95 private volatile bool m_tainted;
111 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); 96 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5);
112
113 private String m_InitialTerrain = "pinhead-island"; 97 private String m_InitialTerrain = "pinhead-island";
114 98
115 // If true, send terrain patch updates to clients based on their view distance 99 // If true, send terrain patch updates to clients based on their view distance
@@ -136,14 +120,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain
136 { 120 {
137 return (updateCount > 0); 121 return (updateCount > 0);
138 } 122 }
123
139 public void SetByXY(int x, int y, bool state) 124 public void SetByXY(int x, int y, bool state)
140 { 125 {
141 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state); 126 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
142 } 127 }
128
143 public bool GetByPatch(int patchX, int patchY) 129 public bool GetByPatch(int patchX, int patchY)
144 { 130 {
145 return updated[patchX, patchY]; 131 return updated[patchX, patchY];
146 } 132 }
133
147 public void SetByPatch(int patchX, int patchY, bool state) 134 public void SetByPatch(int patchX, int patchY, bool state)
148 { 135 {
149 bool prevState = updated[patchX, patchY]; 136 bool prevState = updated[patchX, patchY];
@@ -153,11 +140,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
153 updateCount--; 140 updateCount--;
154 updated[patchX, patchY] = state; 141 updated[patchX, patchY] = state;
155 } 142 }
143
156 public void SetAll(bool state) 144 public void SetAll(bool state)
157 { 145 {
158 updateCount = 0; 146 updateCount = 0;
159 for (int xx = 0; xx < updated.GetLength(0); xx++) 147 for(int xx = 0; xx < updated.GetLength(0); xx++)
160 for (int yy = 0; yy < updated.GetLength(1); yy++) 148 for(int yy = 0; yy < updated.GetLength(1); yy++)
161 updated[xx, yy] = state; 149 updated[xx, yy] = state;
162 if (state) 150 if (state)
163 updateCount = updated.GetLength(0) * updated.GetLength(1); 151 updateCount = updated.GetLength(0) * updated.GetLength(1);
@@ -174,9 +162,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
174 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) 162 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
175 ); 163 );
176 } 164 }
177 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) 165 for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
178 { 166 {
179 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) 167 for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
180 { 168 {
181 // Only set tainted. The patch bit may be set if the patch was to be sent later. 169 // Only set tainted. The patch bit may be set if the patch was to be sent later.
182 if (terrData.IsTaintedAt(xx, yy, false)) 170 if (terrData.IsTaintedAt(xx, yy, false))
@@ -201,8 +189,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
201 189
202 #region ICommandableModule Members 190 #region ICommandableModule Members
203 191
204 public ICommander CommandInterface 192 public ICommander CommandInterface {
205 {
206 get { return m_commander; } 193 get { return m_commander; }
207 } 194 }
208 195
@@ -230,7 +217,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
230 m_scene = scene; 217 m_scene = scene;
231 218
232 // Install terrain module in the simulator 219 // Install terrain module in the simulator
233 lock (m_scene) 220 lock(m_scene)
234 { 221 {
235 if (m_scene.Heightmap == null) 222 if (m_scene.Heightmap == null)
236 { 223 {
@@ -262,7 +249,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
262 string supportedFilesSeparatorForTileSave = ""; 249 string supportedFilesSeparatorForTileSave = "";
263 250
264 m_supportFileExtensionsForTileSave = ""; 251 m_supportFileExtensionsForTileSave = "";
265 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 252 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
266 { 253 {
267 m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; 254 m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")";
268 supportedFilesSeparator = ", "; 255 supportedFilesSeparator = ", ";
@@ -285,7 +272,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
285 272
286 public void RemoveRegion(Scene scene) 273 public void RemoveRegion(Scene scene)
287 { 274 {
288 lock (m_scene) 275 lock(m_scene)
289 { 276 {
290 // remove the commands 277 // remove the commands
291 m_scene.UnregisterModuleCommander(m_commander.Name); 278 m_scene.UnregisterModuleCommander(m_commander.Name);
@@ -304,13 +291,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
304 { 291 {
305 } 292 }
306 293
307 public Type ReplaceableInterface 294 public Type ReplaceableInterface {
308 {
309 get { return null; } 295 get { return null; }
310 } 296 }
311 297
312 public string Name 298 public string Name {
313 {
314 get { return "TerrainModule"; } 299 get { return "TerrainModule"; }
315 } 300 }
316 301
@@ -329,11 +314,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
329 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> 314 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
330 public void LoadFromFile(string filename) 315 public void LoadFromFile(string filename)
331 { 316 {
332 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 317 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
333 { 318 {
334 if (filename.EndsWith(loader.Key)) 319 if (filename.EndsWith(loader.Key))
335 { 320 {
336 lock (m_scene) 321 lock(m_scene)
337 { 322 {
338 try 323 try
339 { 324 {
@@ -349,20 +334,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain
349 m_channel = channel; 334 m_channel = channel;
350 UpdateRevertMap(); 335 UpdateRevertMap();
351 } 336 }
352 catch (NotImplementedException) 337 catch(NotImplementedException)
353 { 338 {
354 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + 339 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
355 " parser does not support file loading. (May be save only)"); 340 " 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)); 341 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value));
357 } 342 }
358 catch (FileNotFoundException) 343 catch(FileNotFoundException)
359 { 344 {
360 m_log.Error( 345 m_log.Error(
361 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); 346 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)");
362 throw new TerrainException( 347 throw new TerrainException(
363 String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); 348 String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename));
364 } 349 }
365 catch (ArgumentException e) 350 catch(ArgumentException e)
366 { 351 {
367 m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); 352 m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message);
368 throw new TerrainException( 353 throw new TerrainException(
@@ -386,7 +371,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
386 { 371 {
387 try 372 try
388 { 373 {
389 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 374 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
390 { 375 {
391 if (filename.EndsWith(loader.Key)) 376 if (filename.EndsWith(loader.Key))
392 { 377 {
@@ -396,7 +381,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
396 } 381 }
397 } 382 }
398 } 383 }
399 catch (IOException ioe) 384 catch(IOException ioe)
400 { 385 {
401 m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message)); 386 m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message));
402 } 387 }
@@ -429,11 +414,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
429 public void LoadFromStream(string filename, Vector3 displacement, 414 public void LoadFromStream(string filename, Vector3 displacement,
430 float radianRotation, Vector2 rotationDisplacement, Stream stream) 415 float radianRotation, Vector2 rotationDisplacement, Stream stream)
431 { 416 {
432 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 417 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
433 { 418 {
434 if (filename.EndsWith(loader.Key)) 419 if (filename.EndsWith(loader.Key))
435 { 420 {
436 lock (m_scene) 421 lock(m_scene)
437 { 422 {
438 try 423 try
439 { 424 {
@@ -441,7 +426,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
441 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); 426 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
442 UpdateRevertMap(); 427 UpdateRevertMap();
443 } 428 }
444 catch (NotImplementedException) 429 catch(NotImplementedException)
445 { 430 {
446 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + 431 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
447 " parser does not support file loading. (May be save only)"); 432 " parser does not support file loading. (May be save only)");
@@ -501,7 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
501 { 486 {
502 try 487 try
503 { 488 {
504 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 489 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
505 { 490 {
506 if (filename.EndsWith(loader.Key)) 491 if (filename.EndsWith(loader.Key))
507 { 492 {
@@ -510,7 +495,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
510 } 495 }
511 } 496 }
512 } 497 }
513 catch (NotImplementedException) 498 catch(NotImplementedException)
514 { 499 {
515 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); 500 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")); 501 throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented"));
@@ -519,12 +504,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
519 504
520 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. 505 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
521 // ITerrainModule.TaintTerrain() 506 // ITerrainModule.TaintTerrain()
522 public void TaintTerrain () 507 public void TaintTerrain()
523 { 508 {
524 lock (m_perClientPatchUpdates) 509 lock(m_perClientPatchUpdates)
525 { 510 {
526 // Set the flags for all clients so the tainted patches will be sent out 511 // Set the flags for all clients so the tainted patches will be sent out
527 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) 512 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values)
528 { 513 {
529 pups.SetAll(m_scene.Heightmap.GetTerrainData()); 514 pups.SetAll(m_scene.Heightmap.GetTerrainData());
530 } 515 }
@@ -539,7 +524,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
539 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 524 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
540 if (presence != null) 525 if (presence != null)
541 { 526 {
542 lock (m_perClientPatchUpdates) 527 lock(m_perClientPatchUpdates)
543 { 528 {
544 PatchUpdates pups; 529 PatchUpdates pups;
545 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) 530 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
@@ -566,13 +551,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
566 m_plugineffects = new Dictionary<string, ITerrainEffect>(); 551 m_plugineffects = new Dictionary<string, ITerrainEffect>();
567 LoadPlugins(Assembly.GetCallingAssembly()); 552 LoadPlugins(Assembly.GetCallingAssembly());
568 string plugineffectsPath = "Terrain"; 553 string plugineffectsPath = "Terrain";
569 554
570 // Load the files in the Terrain/ dir 555 // Load the files in the Terrain/ dir
571 if (!Directory.Exists(plugineffectsPath)) 556 if (!Directory.Exists(plugineffectsPath))
572 return; 557 return;
573 558
574 string[] files = Directory.GetFiles(plugineffectsPath); 559 string[] files = Directory.GetFiles(plugineffectsPath);
575 foreach (string file in files) 560 foreach(string file in files)
576 { 561 {
577 m_log.Info("Loading effects in " + file); 562 m_log.Info("Loading effects in " + file);
578 try 563 try
@@ -580,7 +565,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
580 Assembly library = Assembly.LoadFrom(file); 565 Assembly library = Assembly.LoadFrom(file);
581 LoadPlugins(library); 566 LoadPlugins(library);
582 } 567 }
583 catch (BadImageFormatException) 568 catch(BadImageFormatException)
584 { 569 {
585 } 570 }
586 } 571 }
@@ -588,7 +573,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
588 573
589 private void LoadPlugins(Assembly library) 574 private void LoadPlugins(Assembly library)
590 { 575 {
591 foreach (Type pluginType in library.GetTypes()) 576 foreach(Type pluginType in library.GetTypes())
592 { 577 {
593 try 578 try
594 { 579 {
@@ -610,7 +595,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
610 m_log.Info("L ... " + typeName); 595 m_log.Info("L ... " + typeName);
611 } 596 }
612 } 597 }
613 catch (AmbiguousMatchException) 598 catch(AmbiguousMatchException)
614 { 599 {
615 } 600 }
616 } 601 }
@@ -618,7 +603,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
618 603
619 public void InstallPlugin(string pluginName, ITerrainEffect effect) 604 public void InstallPlugin(string pluginName, ITerrainEffect effect)
620 { 605 {
621 lock (m_plugineffects) 606 lock(m_plugineffects)
622 { 607 {
623 if (!m_plugineffects.ContainsKey(pluginName)) 608 if (!m_plugineffects.ContainsKey(pluginName))
624 { 609 {
@@ -661,8 +646,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
661 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); 646 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
662 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); 647 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert);
663 648
664 // Terrain Feature effects 649 // Terrain Modifier operations
665 m_featureEffects["rectangle"] = new RectangleFeature(this); 650 m_modifyOperations["min"] = new MinModifier(this);
651 m_modifyOperations["max"] = new MaxModifier(this);
652 m_modifyOperations["raise"] = new RaiseModifier(this);
653 m_modifyOperations["lower"] = new LowerModifier(this);
654 m_modifyOperations["fill"] = new FillModifier(this);
655 m_modifyOperations["smooth"] = new SmoothModifier(this);
656 m_modifyOperations["noise"] = new NoiseModifier(this);
666 657
667 // Filesystem load/save loaders 658 // Filesystem load/save loaders
668 m_loaders[".r32"] = new RAW32(); 659 m_loaders[".r32"] = new RAW32();
@@ -707,22 +698,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
707 /// <param name="fileStartY">Where to begin our slice</param> 698 /// <param name="fileStartY">Where to begin our slice</param>
708 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) 699 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY)
709 { 700 {
710 int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX; 701 int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX;
711 int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY; 702 int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY;
712 703
713 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) 704 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight)
714 { 705 {
715 // this region is included in the tile request 706 // this region is included in the tile request
716 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 707 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
717 { 708 {
718 if (filename.EndsWith(loader.Key)) 709 if (filename.EndsWith(loader.Key))
719 { 710 {
720 lock (m_scene) 711 lock(m_scene)
721 { 712 {
722 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 713 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
723 fileWidth, fileHeight, 714 fileWidth, fileHeight,
724 (int) m_scene.RegionInfo.RegionSizeX, 715 (int)m_scene.RegionInfo.RegionSizeX,
725 (int) m_scene.RegionInfo.RegionSizeY); 716 (int)m_scene.RegionInfo.RegionSizeY);
726 m_scene.Heightmap = channel; 717 m_scene.Heightmap = channel;
727 m_channel = channel; 718 m_channel = channel;
728 UpdateRevertMap(); 719 UpdateRevertMap();
@@ -761,11 +752,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
761 } 752 }
762 753
763 // this region is included in the tile request 754 // this region is included in the tile request
764 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 755 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
765 { 756 {
766 if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave()) 757 if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave())
767 { 758 {
768 lock (m_scene) 759 lock(m_scene)
769 { 760 {
770 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, 761 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
771 fileWidth, fileHeight, 762 fileWidth, fileHeight,
@@ -777,7 +768,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
777 fileStartX, fileStartY, fileStartX + fileWidth - 1, fileStartY + fileHeight - 1, 768 fileStartX, fileStartY, fileStartX + fileWidth - 1, fileStartY + fileHeight - 1,
778 m_scene.RegionInfo.RegionName, filename); 769 m_scene.RegionInfo.RegionName, filename);
779 } 770 }
780 771
781 return; 772 return;
782 } 773 }
783 } 774 }
@@ -799,9 +790,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
799 TerrainData terrData = m_channel.GetTerrainData(); 790 TerrainData terrData = m_channel.GetTerrainData();
800 791
801 bool shouldTaint = false; 792 bool shouldTaint = false;
802 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 793 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
803 { 794 {
804 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 795 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
805 { 796 {
806 if (terrData.IsTaintedAt(x, y)) 797 if (terrData.IsTaintedAt(x, y))
807 { 798 {
@@ -856,7 +847,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
856 847
857 string[] tmpArgs = new string[args.Length - 2]; 848 string[] tmpArgs = new string[args.Length - 2];
858 int i; 849 int i;
859 for (i = 2; i < args.Length; i++) 850 for(i = 2; i < args.Length; i++)
860 tmpArgs[i - 2] = args[i]; 851 tmpArgs[i - 2] = args[i];
861 852
862 m_commander.ProcessConsoleCommand(args[1], tmpArgs); 853 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
@@ -874,7 +865,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
874 client.OnLandUndo += client_OnLandUndo; 865 client.OnLandUndo += client_OnLandUndo;
875 client.OnUnackedTerrain += client_OnUnackedTerrain; 866 client.OnUnackedTerrain += client_OnUnackedTerrain;
876 } 867 }
877 868
878 /// <summary> 869 /// <summary>
879 /// Installs terrain brush hook to IClientAPI 870 /// Installs terrain brush hook to IClientAPI
880 /// </summary> 871 /// </summary>
@@ -890,10 +881,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
890 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 881 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
891 } 882 }
892 883
893 lock (m_perClientPatchUpdates) 884 lock(m_perClientPatchUpdates)
894 m_perClientPatchUpdates.Remove(client); 885 m_perClientPatchUpdates.Remove(client);
895 } 886 }
896 887
897 /// <summary> 888 /// <summary>
898 /// Scan over changes in the terrain and limit height changes. This enforces the 889 /// Scan over changes in the terrain and limit height changes. This enforces the
899 /// non-estate owner limits on rate of terrain editting. 890 /// non-estate owner limits on rate of terrain editting.
@@ -904,12 +895,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
904 TerrainData terrData = m_channel.GetTerrainData(); 895 TerrainData terrData = m_channel.GetTerrainData();
905 896
906 bool wasLimited = false; 897 bool wasLimited = false;
907 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 898 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
908 { 899 {
909 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 900 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
910 { 901 {
911 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) 902 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
912 { 903 {
913 // If we should respect the estate settings then 904 // If we should respect the estate settings then
914 // fixup and height deltas that don't respect them. 905 // fixup and height deltas that don't respect them.
915 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. 906 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
@@ -933,9 +924,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
933 924
934 // loop through the height map for this patch and compare it against 925 // loop through the height map for this patch and compare it against
935 // the revert map 926 // the revert map
936 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) 927 for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
937 { 928 {
938 for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 929 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
939 { 930 {
940 float requestedHeight = terrData[x, y]; 931 float requestedHeight = terrData[x, y];
941 float bakedHeight = (float)m_revert[x, y]; 932 float bakedHeight = (float)m_revert[x, y];
@@ -959,7 +950,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
959 950
960 private void client_OnLandUndo(IClientAPI client) 951 private void client_OnLandUndo(IClientAPI client)
961 { 952 {
962 lock (m_undo) 953 lock(m_undo)
963 { 954 {
964 if (m_undo.Count > 0) 955 if (m_undo.Count > 0)
965 { 956 {
@@ -981,19 +972,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
981 if (m_sendTerrainUpdatesByViewDistance) 972 if (m_sendTerrainUpdatesByViewDistance)
982 { 973 {
983 // Add that this patch needs to be sent to the accounting for each client. 974 // Add that this patch needs to be sent to the accounting for each client.
984 lock (m_perClientPatchUpdates) 975 lock(m_perClientPatchUpdates)
985 { 976 {
986 m_scene.ForEachScenePresence(presence => 977 m_scene.ForEachScenePresence(presence =>
978 {
979 PatchUpdates thisClientUpdates;
980 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
987 { 981 {
988 PatchUpdates thisClientUpdates; 982 // There is a ScenePresence without a send patch map. Create one.
989 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) 983 thisClientUpdates = new PatchUpdates(terrData, presence);
990 { 984 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 } 985 }
986 thisClientUpdates.SetByXY(x, y, true);
987 }
997 ); 988 );
998 } 989 }
999 } 990 }
@@ -1005,11 +996,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1005 float[] heightMap = new float[10]; 996 float[] heightMap = new float[10];
1006 m_scene.ForEachClient( 997 m_scene.ForEachClient(
1007 delegate(IClientAPI controller) 998 delegate(IClientAPI controller)
1008 { 999 {
1009 controller.SendLayerData(x / Constants.TerrainPatchSize, 1000 controller.SendLayerData(x / Constants.TerrainPatchSize,
1010 y / Constants.TerrainPatchSize, 1001 y / Constants.TerrainPatchSize,
1011 heightMap); 1002 heightMap);
1012 } 1003 }
1013 ); 1004 );
1014 } 1005 }
1015 } 1006 }
@@ -1019,12 +1010,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1019 public int PatchX; 1010 public int PatchX;
1020 public int PatchY; 1011 public int PatchY;
1021 public float Dist; 1012 public float Dist;
1013
1022 public PatchesToSend(int pX, int pY, float pDist) 1014 public PatchesToSend(int pX, int pY, float pDist)
1023 { 1015 {
1024 PatchX = pX; 1016 PatchX = pX;
1025 PatchY = pY; 1017 PatchY = pY;
1026 Dist = pDist; 1018 Dist = pDist;
1027 } 1019 }
1020
1028 public int CompareTo(PatchesToSend other) 1021 public int CompareTo(PatchesToSend other)
1029 { 1022 {
1030 return Dist.CompareTo(other.Dist); 1023 return Dist.CompareTo(other.Dist);
@@ -1036,9 +1029,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1036 // Loop through all the per-client info and send any patches necessary. 1029 // Loop through all the per-client info and send any patches necessary.
1037 private void CheckSendingPatchesToClients() 1030 private void CheckSendingPatchesToClients()
1038 { 1031 {
1039 lock (m_perClientPatchUpdates) 1032 lock(m_perClientPatchUpdates)
1040 { 1033 {
1041 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) 1034 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values)
1042 { 1035 {
1043 if (pups.HasUpdates()) 1036 if (pups.HasUpdates())
1044 { 1037 {
@@ -1062,7 +1055,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1062 int[] yPieces = new int[toSend.Count]; 1055 int[] yPieces = new int[toSend.Count];
1063 float[] patchPieces = new float[toSend.Count * 2]; 1056 float[] patchPieces = new float[toSend.Count * 2];
1064 int pieceIndex = 0; 1057 int pieceIndex = 0;
1065 foreach (PatchesToSend pts in toSend) 1058 foreach(PatchesToSend pts in toSend)
1066 { 1059 {
1067 patchPieces[pieceIndex++] = pts.PatchX; 1060 patchPieces[pieceIndex++] = pts.PatchX;
1068 patchPieces[pieceIndex++] = pts.PatchY; 1061 patchPieces[pieceIndex++] = pts.PatchY;
@@ -1083,25 +1076,25 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1083 return ret; 1076 return ret;
1084 1077
1085 // Compute the area of patches within our draw distance 1078 // Compute the area of patches within our draw distance
1086 int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; 1079 int startX = (((int)(presence.AbsolutePosition.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
1087 startX = Math.Max(startX, 0); 1080 startX = Math.Max(startX, 0);
1088 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); 1081 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
1089 int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; 1082 int startY = (((int)(presence.AbsolutePosition.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
1090 startY = Math.Max(startY, 0); 1083 startY = Math.Max(startY, 0);
1091 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); 1084 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
1092 int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; 1085 int endX = (((int)(presence.AbsolutePosition.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
1093 endX = Math.Max(endX, 0); 1086 endX = Math.Max(endX, 0);
1094 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); 1087 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
1095 int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; 1088 int endY = (((int)(presence.AbsolutePosition.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
1096 endY = Math.Max(endY, 0); 1089 endY = Math.Max(endY, 0);
1097 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); 1090 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}>", 1091 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
1099 // LogHeader, m_scene.RegionInfo.RegionName, 1092 // LogHeader, m_scene.RegionInfo.RegionName,
1100 // presence.DrawDistance, presence.AbsolutePosition, 1093 // presence.DrawDistance, presence.AbsolutePosition,
1101 // startX, startY, endX, endY); 1094 // startX, startY, endX, endY);
1102 for (int x = startX; x < endX; x++) 1095 for(int x = startX; x < endX; x++)
1103 { 1096 {
1104 for (int y = startY; y < endY; y++) 1097 for(int y = startY; y < endY; y++)
1105 { 1098 {
1106 //Need to make sure we don't send the same ones over and over 1099 //Need to make sure we don't send the same ones over and over
1107 Vector3 presencePos = presence.AbsolutePosition; 1100 Vector3 presencePos = presence.AbsolutePosition;
@@ -1133,28 +1126,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1133 bool allowed = false; 1126 bool allowed = false;
1134 if (north == south && east == west) 1127 if (north == south && east == west)
1135 { 1128 {
1136 if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) 1129 if (m_painteffects.ContainsKey((StandardTerrainEffects)action))
1137 { 1130 {
1138 bool[,] allowMask = new bool[m_channel.Width,m_channel.Height]; 1131 bool[,] allowMask = new bool[m_channel.Width, m_channel.Height];
1139 allowMask.Initialize(); 1132 allowMask.Initialize();
1140 int n = size + 1; 1133 int n = size + 1;
1141 if (n > 2) 1134 if (n > 2)
1142 n = 4; 1135 n = 4;
1143 1136
1144 int zx = (int) (west + 0.5); 1137 int zx = (int)(west + 0.5);
1145 int zy = (int) (north + 0.5); 1138 int zy = (int)(north + 0.5);
1146 1139
1147 int dx; 1140 int dx;
1148 for (dx=-n; dx<=n; dx++) 1141 for(dx=-n; dx<=n; dx++)
1149 { 1142 {
1150 int dy; 1143 int dy;
1151 for (dy=-n; dy<=n; dy++) 1144 for(dy=-n; dy<=n; dy++)
1152 { 1145 {
1153 int x = zx + dx; 1146 int x = zx + dx;
1154 int y = zy + dy; 1147 int y = zy + dy;
1155 if (x>=0 && y>=0 && x<m_channel.Width && y<m_channel.Height) 1148 if (x >= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height)
1156 { 1149 {
1157 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) 1150 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1158 { 1151 {
1159 allowMask[x, y] = true; 1152 allowMask[x, y] = true;
1160 allowed = true; 1153 allowed = true;
@@ -1165,7 +1158,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1165 if (allowed) 1158 if (allowed)
1166 { 1159 {
1167 StoreUndoState(); 1160 StoreUndoState();
1168 m_painteffects[(StandardTerrainEffects) action].PaintEffect( 1161 m_painteffects[(StandardTerrainEffects)action].PaintEffect(
1169 m_channel, allowMask, west, south, height, size, seconds); 1162 m_channel, allowMask, west, south, height, size, seconds);
1170 1163
1171 //revert changes outside estate limits 1164 //revert changes outside estate limits
@@ -1180,22 +1173,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1180 } 1173 }
1181 else 1174 else
1182 { 1175 {
1183 if (m_floodeffects.ContainsKey((StandardTerrainEffects) action)) 1176 if (m_floodeffects.ContainsKey((StandardTerrainEffects)action))
1184 { 1177 {
1185 bool[,] fillArea = new bool[m_channel.Width,m_channel.Height]; 1178 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
1186 fillArea.Initialize(); 1179 fillArea.Initialize();
1187 1180
1188 int x; 1181 int x;
1189 for (x = 0; x < m_channel.Width; x++) 1182 for(x = 0; x < m_channel.Width; x++)
1190 { 1183 {
1191 int y; 1184 int y;
1192 for (y = 0; y < m_channel.Height; y++) 1185 for(y = 0; y < m_channel.Height; y++)
1193 { 1186 {
1194 if (x < east && x > west) 1187 if (x < east && x > west)
1195 { 1188 {
1196 if (y < north && y > south) 1189 if (y < north && y > south)
1197 { 1190 {
1198 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) 1191 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1199 { 1192 {
1200 fillArea[x, y] = true; 1193 fillArea[x, y] = true;
1201 allowed = true; 1194 allowed = true;
@@ -1208,7 +1201,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1208 if (allowed) 1201 if (allowed)
1209 { 1202 {
1210 StoreUndoState(); 1203 StoreUndoState();
1211 m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size); 1204 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size);
1212 1205
1213 //revert changes outside estate limits 1206 //revert changes outside estate limits
1214 if (!god) 1207 if (!god)
@@ -1232,7 +1225,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1232 InterfaceBakeTerrain(null); //bake terrain does not use the passed in parameter 1225 InterfaceBakeTerrain(null); //bake terrain does not use the passed in parameter
1233 } 1226 }
1234 } 1227 }
1235 1228
1236 protected void client_OnUnackedTerrain(IClientAPI client, int patchX, int patchY) 1229 protected void client_OnUnackedTerrain(IClientAPI client, int patchX, int patchY)
1237 { 1230 {
1238 //m_log.Debug("Terrain packet unacked, resending patch: " + patchX + " , " + patchY); 1231 //m_log.Debug("Terrain packet unacked, resending patch: " + patchX + " , " + patchY);
@@ -1243,7 +1236,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1243 1236
1244 private void StoreUndoState() 1237 private void StoreUndoState()
1245 { 1238 {
1246 lock (m_undo) 1239 lock(m_undo)
1247 { 1240 {
1248 if (m_undo.Count > 0) 1241 if (m_undo.Count > 0)
1249 { 1242 {
@@ -1264,21 +1257,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1264 1257
1265 private void InterfaceLoadFile(Object[] args) 1258 private void InterfaceLoadFile(Object[] args)
1266 { 1259 {
1267 LoadFromFile((string) args[0]); 1260 LoadFromFile((string)args[0]);
1268 } 1261 }
1269 1262
1270 private void InterfaceLoadTileFile(Object[] args) 1263 private void InterfaceLoadTileFile(Object[] args)
1271 { 1264 {
1272 LoadFromFile((string) args[0], 1265 LoadFromFile((string)args[0],
1273 (int) args[1], 1266 (int)args[1],
1274 (int) args[2], 1267 (int)args[2],
1275 (int) args[3], 1268 (int)args[3],
1276 (int) args[4]); 1269 (int)args[4]);
1277 } 1270 }
1278 1271
1279 private void InterfaceSaveFile(Object[] args) 1272 private void InterfaceSaveFile(Object[] args)
1280 { 1273 {
1281 SaveToFile((string) args[0]); 1274 SaveToFile((string)args[0]);
1282 } 1275 }
1283 1276
1284 private void InterfaceSaveTileFile(Object[] args) 1277 private void InterfaceSaveTileFile(Object[] args)
@@ -1298,8 +1291,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1298 private void InterfaceRevertTerrain(Object[] args) 1291 private void InterfaceRevertTerrain(Object[] args)
1299 { 1292 {
1300 int x, y; 1293 int x, y;
1301 for (x = 0; x < m_channel.Width; x++) 1294 for(x = 0; x < m_channel.Width; x++)
1302 for (y = 0; y < m_channel.Height; y++) 1295 for(y = 0; y < m_channel.Height; y++)
1303 m_channel[x, y] = m_revert[x, y]; 1296 m_channel[x, y] = m_revert[x, y];
1304 1297
1305 } 1298 }
@@ -1310,9 +1303,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1310 1303
1311 if (direction.ToLower().StartsWith("y")) 1304 if (direction.ToLower().StartsWith("y"))
1312 { 1305 {
1313 for (int x = 0; x < m_channel.Width; x++) 1306 for(int x = 0; x < m_channel.Width; x++)
1314 { 1307 {
1315 for (int y = 0; y < m_channel.Height / 2; y++) 1308 for(int y = 0; y < m_channel.Height / 2; y++)
1316 { 1309 {
1317 double height = m_channel[x, y]; 1310 double height = m_channel[x, y];
1318 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; 1311 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
@@ -1324,9 +1317,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1324 } 1317 }
1325 else if (direction.ToLower().StartsWith("x")) 1318 else if (direction.ToLower().StartsWith("x"))
1326 { 1319 {
1327 for (int y = 0; y < m_channel.Height; y++) 1320 for(int y = 0; y < m_channel.Height; y++)
1328 { 1321 {
1329 for (int x = 0; x < m_channel.Width / 2; x++) 1322 for(int x = 0; x < m_channel.Width / 2; x++)
1330 { 1323 {
1331 double height = m_channel[x, y]; 1324 double height = m_channel[x, y];
1332 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; 1325 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
@@ -1365,9 +1358,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1365 int width = m_channel.Width; 1358 int width = m_channel.Width;
1366 int height = m_channel.Height; 1359 int height = m_channel.Height;
1367 1360
1368 for (int x = 0; x < width; x++) 1361 for(int x = 0; x < width; x++)
1369 { 1362 {
1370 for (int y = 0; y < height; y++) 1363 for(int y = 0; y < height; y++)
1371 { 1364 {
1372 double currHeight = m_channel[x, y]; 1365 double currHeight = m_channel[x, y];
1373 if (currHeight < currMin) 1366 if (currHeight < currMin)
@@ -1388,12 +1381,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1388 //m_log.InfoFormat("Scale = {0}", scale); 1381 //m_log.InfoFormat("Scale = {0}", scale);
1389 1382
1390 // scale the heightmap accordingly 1383 // scale the heightmap accordingly
1391 for (int x = 0; x < width; x++) 1384 for(int x = 0; x < width; x++)
1392 { 1385 {
1393 for (int y = 0; y < height; y++) 1386 for(int y = 0; y < height; y++)
1394 { 1387 {
1395 double currHeight = m_channel[x, y] - currMin; 1388 double currHeight = m_channel[x, y] - currMin;
1396 m_channel[x, y] = desiredMin + (currHeight * scale); 1389 m_channel[x, y] = desiredMin + (currHeight * scale);
1397 } 1390 }
1398 } 1391 }
1399 1392
@@ -1404,42 +1397,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1404 private void InterfaceElevateTerrain(Object[] args) 1397 private void InterfaceElevateTerrain(Object[] args)
1405 { 1398 {
1406 int x, y; 1399 int x, y;
1407 for (x = 0; x < m_channel.Width; x++) 1400 for(x = 0; x < m_channel.Width; x++)
1408 for (y = 0; y < m_channel.Height; y++) 1401 for(y = 0; y < m_channel.Height; y++)
1409 m_channel[x, y] += (double) args[0]; 1402 m_channel[x, y] += (double)args[0];
1410 } 1403 }
1411 1404
1412 private void InterfaceMultiplyTerrain(Object[] args) 1405 private void InterfaceMultiplyTerrain(Object[] args)
1413 { 1406 {
1414 int x, y; 1407 int x, y;
1415 for (x = 0; x < m_channel.Width; x++) 1408 for(x = 0; x < m_channel.Width; x++)
1416 for (y = 0; y < m_channel.Height; y++) 1409 for(y = 0; y < m_channel.Height; y++)
1417 m_channel[x, y] *= (double) args[0]; 1410 m_channel[x, y] *= (double)args[0];
1418 } 1411 }
1419 1412
1420 private void InterfaceLowerTerrain(Object[] args) 1413 private void InterfaceLowerTerrain(Object[] args)
1421 { 1414 {
1422 int x, y; 1415 int x, y;
1423 for (x = 0; x < m_channel.Width; x++) 1416 for(x = 0; x < m_channel.Width; x++)
1424 for (y = 0; y < m_channel.Height; y++) 1417 for(y = 0; y < m_channel.Height; y++)
1425 m_channel[x, y] -= (double) args[0]; 1418 m_channel[x, y] -= (double)args[0];
1426 } 1419 }
1427 1420
1428 public void InterfaceFillTerrain(Object[] args) 1421 public void InterfaceFillTerrain(Object[] args)
1429 { 1422 {
1430 int x, y; 1423 int x, y;
1431 1424
1432 for (x = 0; x < m_channel.Width; x++) 1425 for(x = 0; x < m_channel.Width; x++)
1433 for (y = 0; y < m_channel.Height; y++) 1426 for(y = 0; y < m_channel.Height; y++)
1434 m_channel[x, y] = (double) args[0]; 1427 m_channel[x, y] = (double)args[0];
1435 } 1428 }
1436 1429
1437 private void InterfaceMinTerrain(Object[] args) 1430 private void InterfaceMinTerrain(Object[] args)
1438 { 1431 {
1439 int x, y; 1432 int x, y;
1440 for (x = 0; x < m_channel.Width; x++) 1433 for(x = 0; x < m_channel.Width; x++)
1441 { 1434 {
1442 for (y = 0; y < m_channel.Height; y++) 1435 for(y = 0; y < m_channel.Height; y++)
1443 { 1436 {
1444 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1437 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
1445 } 1438 }
@@ -1449,9 +1442,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1449 private void InterfaceMaxTerrain(Object[] args) 1442 private void InterfaceMaxTerrain(Object[] args)
1450 { 1443 {
1451 int x, y; 1444 int x, y;
1452 for (x = 0; x < m_channel.Width; x++) 1445 for(x = 0; x < m_channel.Width; x++)
1453 { 1446 {
1454 for (y = 0; y < m_channel.Height; y++) 1447 for(y = 0; y < m_channel.Height; y++)
1455 { 1448 {
1456 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1449 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
1457 } 1450 }
@@ -1480,10 +1473,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1480 double sum = 0; 1473 double sum = 0;
1481 1474
1482 int x; 1475 int x;
1483 for (x = 0; x < m_channel.Width; x++) 1476 for(x = 0; x < m_channel.Width; x++)
1484 { 1477 {
1485 int y; 1478 int y;
1486 for (y = 0; y < m_channel.Height; y++) 1479 for(y = 0; y < m_channel.Height; y++)
1487 { 1480 {
1488 sum += m_channel[x, y]; 1481 sum += m_channel[x, y];
1489 if (max < m_channel[x, y]) 1482 if (max < m_channel[x, y])
@@ -1501,7 +1494,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1501 1494
1502 private void InterfaceEnableExperimentalBrushes(Object[] args) 1495 private void InterfaceEnableExperimentalBrushes(Object[] args)
1503 { 1496 {
1504 if ((bool) args[0]) 1497 if ((bool)args[0])
1505 { 1498 {
1506 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); 1499 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere();
1507 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); 1500 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere();
@@ -1520,7 +1513,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1520 if (firstArg == "list") 1513 if (firstArg == "list")
1521 { 1514 {
1522 MainConsole.Instance.Output("List of loaded plugins"); 1515 MainConsole.Instance.Output("List of loaded plugins");
1523 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1516 foreach(KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
1524 { 1517 {
1525 MainConsole.Instance.Output(kvp.Key); 1518 MainConsole.Instance.Output(kvp.Key);
1526 } 1519 }
@@ -1665,46 +1658,65 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1665 // Add this to our scene so scripts can call these functions 1658 // Add this to our scene so scripts can call these functions
1666 m_scene.RegisterModuleCommander(m_commander); 1659 m_scene.RegisterModuleCommander(m_commander);
1667 1660
1668 // Add Feature command to Scene, since Command object requires fixed-length arglists 1661 // Add Modify command to Scene, since Command object requires fixed-length arglists
1669 m_scene.AddCommand("Terrain", this, "terrain feature", 1662 m_scene.AddCommand("Terrain", this, "terrain modify",
1670 "terrain feature <type> <parameters...>", "Constructs a feature of the requested type.", FeatureCommand); 1663 "terrain modify <operation> <value> [<area>] [<taper>]",
1664 "Modifies the terrain as instructed." +
1665 "\nEach operation can be limited to an area of effect:" +
1666 "\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" +
1667 "\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" +
1668 "\nEach operation can have its effect tapered based on distance from centre:" +
1669 "\n * elliptical operations taper as cones" +
1670 "\n * rectangular operations taper as pyramids"
1671 ,
1672 ModifyCommand);
1671 1673
1672 } 1674 }
1673 1675
1674 public void FeatureCommand(string module, string[] cmd) 1676 public void ModifyCommand(string module, string[] cmd)
1675 { 1677 {
1676 string result; 1678 string result;
1677 if (cmd.Length > 2) 1679 Scene scene = SceneManager.Instance.CurrentScene;
1680 if ((scene != null) && (scene != m_scene))
1681 {
1682 result = String.Empty;
1683 }
1684 else if (cmd.Length > 2)
1678 { 1685 {
1679 string featureType = cmd[2]; 1686 string operationType = cmd[2];
1687
1680 1688
1681 ITerrainFeature feature; 1689 ITerrainModifier operation;
1682 if (!m_featureEffects.TryGetValue(featureType, out feature)) 1690 if (!m_modifyOperations.TryGetValue(operationType, out operation))
1683 { 1691 {
1684 result = String.Format("Terrain Feature \"{0}\" not found.", featureType); 1692 result = String.Format("Terrain Modify \"{0}\" not found.", operationType);
1685 } 1693 }
1686 else if ((cmd.Length > 3) && (cmd[3] == "usage")) 1694 else if ((cmd.Length > 3) && (cmd[3] == "usage"))
1687 { 1695 {
1688 result = "Usage: " + feature.GetUsage(); 1696 result = "Usage: " + operation.GetUsage();
1689 } 1697 }
1690 else 1698 else
1691 { 1699 {
1692 result = feature.CreateFeature(m_channel, cmd); 1700 result = operation.ModifyTerrain(m_channel, cmd);
1693 } 1701 }
1694 1702
1695 if(result == String.Empty) 1703 if (result == String.Empty)
1696 { 1704 {
1697 result = "Created Feature"; 1705 result = "Modified terrain";
1698 m_log.DebugFormat("Created terrain feature {0}", featureType); 1706 m_log.DebugFormat("Performed terrain operation {0}", operationType);
1699 } 1707 }
1700 } 1708 }
1701 else 1709 else
1702 { 1710 {
1703 result = "Usage: <feature-name> <arg1> <arg2>..."; 1711 result = "Usage: <operation-name> <arg1> <arg2>...";
1712 }
1713 if (result != String.Empty)
1714 {
1715 MainConsole.Instance.Output(result);
1704 } 1716 }
1705 MainConsole.Instance.Output(result);
1706 } 1717 }
1707 #endregion 1718
1719#endregion
1708 1720
1709 } 1721 }
1710} 1722}