aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
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
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')
-rw-r--r--OpenSim/Region/Application/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs209
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs30
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs29
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs36
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs18
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs13
-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
-rw-r--r--OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs2
-rwxr-xr-xOpenSim/Region/Framework/Scenes/Scene.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs136
-rw-r--r--OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs41
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs15
-rw-r--r--OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs1308
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs2
50 files changed, 3036 insertions, 687 deletions
diff --git a/OpenSim/Region/Application/Properties/AssemblyInfo.cs b/OpenSim/Region/Application/Properties/AssemblyInfo.cs
index 650425b..8652312 100644
--- a/OpenSim/Region/Application/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Application/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.8.1.*")] 33[assembly: AssemblyVersion("0.8.2.*")]
34 34
35[assembly: AddinRoot("OpenSim", OpenSim.VersionInfo.VersionNumber)] 35[assembly: AddinRoot("OpenSim", OpenSim.VersionInfo.VersionNumber)]
36[assembly: ImportAddinAssembly("OpenSim.Framework.dll")] 36[assembly: ImportAddinAssembly("OpenSim.Framework.dll")]
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
index 3bc0be8..264eaa3 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 053a6a2..30d1921 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -201,11 +201,12 @@ namespace OpenSim.Region.ClientStack.Linden
201 201
202 Scene.EventManager.OnRegisterCaps += RegisterCaps; 202 Scene.EventManager.OnRegisterCaps += RegisterCaps;
203 203
204 int nworkers = 2; // was 2
204 if (ProcessQueuedRequestsAsync && m_workerThreads == null) 205 if (ProcessQueuedRequestsAsync && m_workerThreads == null)
205 { 206 {
206 m_workerThreads = new Thread[2]; 207 m_workerThreads = new Thread[nworkers];
207 208
208 for (uint i = 0; i < 2; i++) 209 for (uint i = 0; i < nworkers; i++)
209 { 210 {
210 m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests, 211 m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests,
211 String.Format("InventoryWorkerThread{0}", i), 212 String.Format("InventoryWorkerThread{0}", i),
@@ -364,7 +365,11 @@ namespace OpenSim.Region.ClientStack.Linden
364 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); 365 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
365 366
366 lock (responses) 367 lock (responses)
368 {
369 if (responses.ContainsKey(requestID))
370 m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054");
367 responses[requestID] = response; 371 responses[requestID] = response;
372 }
368 373
369 WebFetchInvDescModule.ProcessedRequestsCount++; 374 WebFetchInvDescModule.ProcessedRequestsCount++;
370 } 375 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 311dd31..284c5fa 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -3747,6 +3747,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3747 avp.Sender.IsTrial = false; 3747 avp.Sender.IsTrial = false;
3748 avp.Sender.ID = agentID; 3748 avp.Sender.ID = agentID;
3749 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; 3749 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
3750 avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0];
3750 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); 3751 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3751 OutPacket(avp, ThrottleOutPacketType.Task); 3752 OutPacket(avp, ThrottleOutPacketType.Task);
3752 } 3753 }
@@ -4465,7 +4466,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4465 { 4466 {
4466 uint priority = 0; // time based ordering only 4467 uint priority = 0; // time based ordering only
4467 lock (m_entityProps.SyncRoot) 4468 lock (m_entityProps.SyncRoot)
4468 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); 4469 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true));
4469 } 4470 }
4470 4471
4471 private void ResendPropertyUpdate(ObjectPropertyUpdate update) 4472 private void ResendPropertyUpdate(ObjectPropertyUpdate update)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
index 8ce1b85..8795c0c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index 75f0774..f54298c 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -35,6 +35,7 @@ using System.Xml;
35using log4net; 35using log4net;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Serialization.External;
38 39
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.Framework.Scenes.Serialization; 41using OpenSim.Region.Framework.Scenes.Serialization;
@@ -189,217 +190,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
189 return Utils.StringToBytes(RewriteSOP(xml)); 190 return Utils.StringToBytes(RewriteSOP(xml));
190 } 191 }
191 192
192 protected void TransformXml(XmlReader reader, XmlWriter writer)
193 {
194// m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML");
195
196 int sopDepth = -1;
197 UserAccount creator = null;
198 bool hasCreatorData = false;
199
200 while (reader.Read())
201 {
202// Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name);
203
204 switch (reader.NodeType)
205 {
206 case XmlNodeType.Attribute:
207// Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name);
208 writer.WriteAttributeString(reader.Prefix, reader.Name, reader.NamespaceURI, reader.Value);
209 break;
210
211 case XmlNodeType.CDATA:
212 writer.WriteCData(reader.Value);
213 break;
214
215 case XmlNodeType.Comment:
216 writer.WriteComment(reader.Value);
217 break;
218
219 case XmlNodeType.DocumentType:
220 writer.WriteDocType(reader.Name, reader.Value, null, null);
221 break;
222
223 case XmlNodeType.Element:
224// m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name);
225
226 writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
227
228 if (reader.HasAttributes)
229 {
230 while (reader.MoveToNextAttribute())
231 writer.WriteAttributeString(reader.Prefix, reader.Name, reader.NamespaceURI, reader.Value);
232
233 reader.MoveToElement();
234 }
235
236 if (reader.LocalName == "SceneObjectPart")
237 {
238 if (sopDepth < 0)
239 {
240 sopDepth = reader.Depth;
241// m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth);
242 }
243 }
244 else
245 {
246 if (sopDepth >= 0 && reader.Depth == sopDepth + 1)
247 {
248 if (reader.Name == "CreatorID")
249 {
250 reader.Read();
251 if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID")
252 {
253 reader.Read();
254
255 if (reader.NodeType == XmlNodeType.Text)
256 {
257 UUID uuid = UUID.Zero;
258 UUID.TryParse(reader.Value, out uuid);
259 creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
260 writer.WriteElementString("UUID", reader.Value);
261 reader.Read();
262 }
263 else
264 {
265 // If we unexpected run across mixed content in this node, still carry on
266 // transforming the subtree (this replicates earlier behaviour).
267 TransformXml(reader, writer);
268 }
269 }
270 else
271 {
272 // If we unexpected run across mixed content in this node, still carry on
273 // transforming the subtree (this replicates earlier behaviour).
274 TransformXml(reader, writer);
275 }
276 }
277 else if (reader.Name == "CreatorData")
278 {
279 reader.Read();
280 if (reader.NodeType == XmlNodeType.Text)
281 {
282 hasCreatorData = true;
283 writer.WriteString(reader.Value);
284 }
285 else
286 {
287 // If we unexpected run across mixed content in this node, still carry on
288 // transforming the subtree (this replicates earlier behaviour).
289 TransformXml(reader, writer);
290 }
291 }
292 }
293 }
294
295 if (reader.IsEmptyElement)
296 {
297// m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name);
298 writer.WriteEndElement();
299 }
300
301 break;
302
303 case XmlNodeType.EndElement:
304// m_log.DebugFormat("Depth {0} at EndElement", reader.Depth);
305 if (sopDepth == reader.Depth)
306 {
307 if (!hasCreatorData && creator != null)
308 writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", m_HomeURI, creator.FirstName, creator.LastName));
309
310// m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth");
311 sopDepth = -1;
312 creator = null;
313 hasCreatorData = false;
314 }
315 writer.WriteEndElement();
316 break;
317
318 case XmlNodeType.EntityReference:
319 writer.WriteEntityRef(reader.Name);
320 break;
321
322 case XmlNodeType.ProcessingInstruction:
323 writer.WriteProcessingInstruction(reader.Name, reader.Value);
324 break;
325
326 case XmlNodeType.Text:
327 writer.WriteString(reader.Value);
328 break;
329
330 case XmlNodeType.XmlDeclaration:
331 // For various reasons, not all serializations have xml declarations (or consistent ones)
332 // and as it's embedded inside a byte stream we don't need it anyway, so ignore.
333 break;
334
335 default:
336 m_log.WarnFormat(
337 "[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}",
338 reader.NodeType, m_scene.Name);
339 break;
340 }
341 }
342 }
343
344 protected string RewriteSOP(string xmlData) 193 protected string RewriteSOP(string xmlData)
345 { 194 {
346// Console.WriteLine("Input XML [{0}]", xmlData); 195// Console.WriteLine("Input XML [{0}]", xmlData);
196 return ExternalRepresentationUtils.RewriteSOP(xmlData, m_scene.Name, m_HomeURI, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID);
347 197
348 using (StringWriter sw = new StringWriter())
349 using (XmlTextWriter writer = new XmlTextWriter(sw))
350 using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
351 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment }))
352 {
353 TransformXml(reader, writer);
354
355// Console.WriteLine("Output: [{0}]", sw.ToString());
356
357 return sw.ToString();
358 }
359
360 // We are now taking the more complex streaming approach above because some assets can be very large
361 // and can trigger higher CPU use or possibly memory problems.
362// XmlDocument doc = new XmlDocument();
363// doc.LoadXml(xml);
364// XmlNodeList sops = doc.GetElementsByTagName("SceneObjectPart");
365//
366// foreach (XmlNode sop in sops)
367// {
368// UserAccount creator = null;
369// bool hasCreatorData = false;
370// XmlNodeList nodes = sop.ChildNodes;
371// foreach (XmlNode node in nodes)
372// {
373// if (node.Name == "CreatorID")
374// {
375// UUID uuid = UUID.Zero;
376// UUID.TryParse(node.InnerText, out uuid);
377// creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
378// }
379// if (node.Name == "CreatorData" && node.InnerText != null && node.InnerText != string.Empty)
380// hasCreatorData = true;
381//
382// //if (node.Name == "OwnerID")
383// //{
384// // UserAccount owner = GetUser(node.InnerText);
385// // if (owner != null)
386// // node.InnerText = m_ProfileServiceURL + "/" + node.InnerText + "/" + owner.FirstName + " " + owner.LastName;
387// //}
388// }
389//
390// if (!hasCreatorData && creator != null)
391// {
392// XmlElement creatorData = doc.CreateElement("CreatorData");
393// creatorData.InnerText = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName;
394// sop.AppendChild(creatorData);
395// }
396// }
397//
398// using (StringWriter wr = new StringWriter())
399// {
400// doc.Save(wr);
401// return wr.ToString();
402// }
403 } 198 }
404 199
405 // TODO: unused 200 // TODO: unused
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
index 01814a1..e657f53 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
65 { 65 {
66 InventoryFolderImpl folder = null; 66 InventoryFolderImpl folder = null;
67 InventoryCollection inv = new InventoryCollection(); 67 InventoryCollection inv = new InventoryCollection();
68 inv.UserID = m_Library.Owner; 68 inv.OwnerID = m_Library.Owner;
69 69
70 if (folderID != m_Library.ID) 70 if (folderID != m_Library.ID)
71 { 71 {
@@ -87,6 +87,34 @@ namespace OpenSim.Region.CoreModules.Framework.Library
87 return inv; 87 return inv;
88 } 88 }
89 89
90 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
91 {
92 InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
93 int i = 0;
94 foreach (UUID fid in folderIDs)
95 {
96 invColl[i++] = GetFolderContent(principalID, fid);
97 }
98
99 return invColl;
100 }
101
102 public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
103 {
104 InventoryItemBase[] itemColl = new InventoryItemBase[itemIDs.Length];
105 int i = 0;
106 InventoryItemBase item = new InventoryItemBase();
107 item.Owner = principalID;
108 foreach (UUID fid in itemIDs)
109 {
110 item.ID = fid;
111 itemColl[i++] = GetItem(item);
112 }
113
114 return itemColl;
115 }
116
117
90 /// <summary> 118 /// <summary>
91 /// Add a new folder to the user's inventory 119 /// Add a new folder to the user's inventory
92 /// </summary> 120 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index ba71dc5..7ecbd26 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
154 154
155 #endregion ISharedRegionModule 155 #endregion ISharedRegionModule
156 156
157 157
158 #region Event Handlers 158 #region Event Handlers
159 159
160 void EventManager_OnPrimsLoaded(Scene s) 160 void EventManager_OnPrimsLoaded(Scene s)
@@ -180,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
180 void HandleUUIDNameRequest(UUID uuid, IClientAPI client) 180 void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
181 { 181 {
182// m_log.DebugFormat( 182// m_log.DebugFormat(
183// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", 183// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
184// uuid, remote_client.Name); 184// uuid, remote_client.Name);
185 185
186 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 186 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
@@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
212 // appear to clear this when the user asks it to clear the cache, but others may not. 212 // appear to clear this when the user asks it to clear the cache, but others may not.
213 // 213 //
214 // So to avoid clients 214 // So to avoid clients
215 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will 215 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
216 // instead drop the request entirely. 216 // instead drop the request entirely.
217 if (GetUser(uuid, out user)) 217 if (GetUser(uuid, out user))
218 { 218 {
@@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
220 } 220 }
221// else 221// else
222// m_log.DebugFormat( 222// m_log.DebugFormat(
223// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}", 223// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
224// uuid, client.Name); 224// uuid, client.Name);
225 }); 225 });
226 } 226 }
@@ -416,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
416 m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e); 416 m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e);
417 userdata.ServerURLs = new Dictionary<string, object>(); 417 userdata.ServerURLs = new Dictionary<string, object>();
418 } 418 }
419 419
420 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) 420 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
421 return userdata.ServerURLs[serverType].ToString(); 421 return userdata.ServerURLs[serverType].ToString();
422 } 422 }
@@ -620,7 +620,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
620 AddUser(id, string.Empty, string.Empty, string.Empty); 620 AddUser(id, string.Empty, string.Empty, string.Empty);
621 } 621 }
622 else 622 else
623 { 623 {
624 string homeURL; 624 string homeURL;
625 string firstname = string.Empty; 625 string firstname = string.Empty;
626 string lastname = string.Empty; 626 string lastname = string.Empty;
@@ -676,7 +676,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
676 else 676 else
677 { 677 {
678 lock(m_UserCache) 678 lock(m_UserCache)
679 { 679 {
680 if(!m_UserCache.ContainsKey(id)) 680 if(!m_UserCache.ContainsKey(id))
681 { 681 {
682 UserData newUser = new UserData(); 682 UserData newUser = new UserData();
@@ -726,6 +726,21 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
726 "Show the bindings between user UUIDs and user names", 726 "Show the bindings between user UUIDs and user names",
727 String.Empty, 727 String.Empty,
728 HandleShowUsers); 728 HandleShowUsers);
729
730 MainConsole.Instance.Commands.AddCommand("Users", true,
731 "reset user cache",
732 "reset user cache",
733 "reset user cache to allow changed settings to be applied",
734 String.Empty,
735 HandleResetUserCache);
736 }
737
738 private void HandleResetUserCache(string module, string[] cmd)
739 {
740 lock(m_UserCache)
741 {
742 m_UserCache.Clear();
743 }
729 } 744 }
730 745
731 private void HandleShowUser(string module, string[] cmd) 746 private void HandleShowUser(string module, string[] cmd)
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
index 1b1b319..64532df 100644
--- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.8.1.*")] 33[assembly: AssemblyVersion("0.8.2.*")]
34 34
35 35
36[assembly: Addin("OpenSim.Region.CoreModules", OpenSim.VersionInfo.VersionNumber)] 36[assembly: Addin("OpenSim.Region.CoreModules", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index e13ee42..6a83b42 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -389,6 +389,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
389 return connector.GetFolderContent(userID, folderID); 389 return connector.GetFolderContent(userID, folderID);
390 } 390 }
391 391
392 public InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs)
393 {
394 string invURL = GetInventoryServiceURL(userID);
395
396 if (invURL == null) // not there, forward to local inventory connector to resolve
397 lock (m_Lock)
398 return m_LocalGridInventoryService.GetMultipleFoldersContent(userID, folderIDs);
399
400 else
401 {
402 InventoryCollection[] coll = new InventoryCollection[folderIDs.Length];
403 int i = 0;
404 foreach (UUID fid in folderIDs)
405 coll[i++] = GetFolderContent(userID, fid);
406
407 return coll;
408 }
409 }
410
392 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 411 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
393 { 412 {
394 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); 413 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID);
@@ -596,6 +615,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
596 return connector.GetItem(item); 615 return connector.GetItem(item);
597 } 616 }
598 617
618 public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
619 {
620 if (itemIDs == null)
621 return new InventoryItemBase[0];
622 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetItem " + item.ID);
623
624 string invURL = GetInventoryServiceURL(userID);
625
626 if (invURL == null) // not there, forward to local inventory connector to resolve
627 lock (m_Lock)
628 return m_LocalGridInventoryService.GetMultipleItems(userID, itemIDs);
629
630 IInventoryService connector = GetConnector(invURL);
631
632 return connector.GetMultipleItems(userID, itemIDs);
633 }
634
599 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 635 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
600 { 636 {
601 if (folder == null) 637 if (folder == null)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
index 499ca5e..71dc337 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
@@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
106 if (m_Inventories.TryGetValue(userID, out inv)) 106 if (m_Inventories.TryGetValue(userID, out inv))
107 { 107 {
108 c = new InventoryCollection(); 108 c = new InventoryCollection();
109 c.UserID = userID; 109 c.OwnerID = userID;
110 110
111 c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f) 111 c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f)
112 { 112 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index cbe0e37..2f29a7c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -195,6 +195,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
195 return invCol; 195 return invCol;
196 } 196 }
197 197
198 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
199 {
200 InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
201 int i = 0;
202 foreach (UUID fid in folderIDs)
203 {
204 invColl[i++] = GetFolderContent(principalID, fid);
205 }
206
207 return invColl;
208
209 }
210
198 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 211 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
199 { 212 {
200 return m_InventoryService.GetFolderItems(userID, folderID); 213 return m_InventoryService.GetFolderItems(userID, folderID);
@@ -294,6 +307,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
294 return item; 307 return item;
295 } 308 }
296 309
310 public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
311 {
312 return m_InventoryService.GetMultipleItems(userID, itemIDs);
313 }
314
297 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 315 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
298 { 316 {
299 return m_InventoryService.GetFolder(folder); 317 return m_InventoryService.GetFolder(folder);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 166e4a1..e0cc1e8 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -204,6 +204,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
204 return invCol; 204 return invCol;
205 } 205 }
206 206
207 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
208 {
209 return m_RemoteConnector.GetMultipleFoldersContent(principalID, folderIDs);
210 }
211
207 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 212 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
208 { 213 {
209 return m_RemoteConnector.GetFolderItems(userID, folderID); 214 return m_RemoteConnector.GetFolderItems(userID, folderID);
@@ -298,6 +303,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
298 return m_RemoteConnector.GetItem(item); 303 return m_RemoteConnector.GetItem(item);
299 } 304 }
300 305
306 public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
307 {
308 if (itemIDs == null)
309 return new InventoryItemBase[0];
310
311 return m_RemoteConnector.GetMultipleItems(userID, itemIDs);
312 }
313
301 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 314 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
302 { 315 {
303 //m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetFolder {0}", folder.ID); 316 //m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetFolder {0}", folder.ID);
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}
diff --git a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
index 637387a..e60d3ae 100644
--- a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
index fd9ab3d..97dea1f 100644
--- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
@@ -31,6 +31,6 @@ using Mono.Addins;
31// Build Number 31// Build Number
32// Revision 32// Revision
33// 33//
34[assembly: AssemblyVersion("0.8.1.*")] 34[assembly: AssemblyVersion("0.8.2.*")]
35[assembly: AddinRoot("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] 35[assembly: AddinRoot("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
36 36
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 31900ec..905bde2 100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1653,7 +1653,7 @@ namespace OpenSim.Region.Framework.Scenes
1653 1653
1654 // These variables will be used to save the precise frame time using the 1654 // These variables will be used to save the precise frame time using the
1655 // Stopwatch class of Microsoft SDK; the times are recorded at the start 1655 // Stopwatch class of Microsoft SDK; the times are recorded at the start
1656 // and end of a parcticular section of code, and then used to calculate 1656 // and end of a particular section of code, and then used to calculate
1657 // the frame times, which are the sums of the sections for each given name 1657 // the frame times, which are the sums of the sections for each given name
1658 double preciseTotalFrameTime = 0.0; 1658 double preciseTotalFrameTime = 0.0;
1659 double preciseSimFrameTime = 0.0; 1659 double preciseSimFrameTime = 0.0;
@@ -1698,7 +1698,7 @@ namespace OpenSim.Region.Framework.Scenes
1698 // input took 1698 // input took
1699 simFrameStopwatch.Stop(); 1699 simFrameStopwatch.Stop();
1700 preciseSimFrameTime = 1700 preciseSimFrameTime =
1701 simFrameStopwatch.Elapsed.TotalMilliseconds; 1701 simFrameStopwatch.Elapsed.TotalMilliseconds;
1702 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); 1702 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1703 } 1703 }
1704 1704
@@ -1717,7 +1717,7 @@ namespace OpenSim.Region.Framework.Scenes
1717 // Begin the stopwatch to track the time to prepare physics 1717 // Begin the stopwatch to track the time to prepare physics
1718 physicsFrameStopwatch.Start(); 1718 physicsFrameStopwatch.Start();
1719 if (PhysicsEnabled && Frame % m_update_physics == 0) 1719 if (PhysicsEnabled && Frame % m_update_physics == 0)
1720 m_sceneGraph.UpdatePreparePhysics(); 1720 m_sceneGraph.UpdatePreparePhysics();
1721 1721
1722 // Get the time it took to prepare the physics, this 1722 // Get the time it took to prepare the physics, this
1723 // would report the most precise time that physics was 1723 // would report the most precise time that physics was
@@ -1738,7 +1738,7 @@ namespace OpenSim.Region.Framework.Scenes
1738 // took 1738 // took
1739 simFrameStopwatch.Stop(); 1739 simFrameStopwatch.Stop();
1740 preciseSimFrameTime += 1740 preciseSimFrameTime +=
1741 simFrameStopwatch.Elapsed.TotalMilliseconds; 1741 simFrameStopwatch.Elapsed.TotalMilliseconds;
1742 agentMS = Util.EnvironmentTickCountSubtract(tmpMS); 1742 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1743 1743
1744 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1744 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
@@ -1851,7 +1851,7 @@ namespace OpenSim.Region.Framework.Scenes
1851 // Get the elapsed time for the simulation frame 1851 // Get the elapsed time for the simulation frame
1852 simFrameStopwatch.Stop(); 1852 simFrameStopwatch.Stop();
1853 preciseSimFrameTime += 1853 preciseSimFrameTime +=
1854 simFrameStopwatch.Elapsed.TotalMilliseconds; 1854 simFrameStopwatch.Elapsed.TotalMilliseconds;
1855 1855
1856 if (!UpdateOnTimer) 1856 if (!UpdateOnTimer)
1857 { 1857 {
@@ -1872,7 +1872,7 @@ namespace OpenSim.Region.Framework.Scenes
1872 // Get the total frame time 1872 // Get the total frame time
1873 totalFrameStopwatch.Stop(); 1873 totalFrameStopwatch.Stop();
1874 preciseTotalFrameTime = 1874 preciseTotalFrameTime =
1875 totalFrameStopwatch.Elapsed.TotalMilliseconds; 1875 totalFrameStopwatch.Elapsed.TotalMilliseconds;
1876 1876
1877 // Restart the stopwatch for the total time of the next frame 1877 // Restart the stopwatch for the total time of the next frame
1878 totalFrameStopwatch.Restart(); 1878 totalFrameStopwatch.Restart();
@@ -1897,7 +1897,7 @@ namespace OpenSim.Region.Framework.Scenes
1897 // Send the correct time values to the stats reporter for the 1897 // Send the correct time values to the stats reporter for the
1898 // frame times 1898 // frame times
1899 StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime, 1899 StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime,
1900 preciseSimFrameTime, precisePhysicsFrameTime, 0.0); 1900 preciseSimFrameTime, precisePhysicsFrameTime, 0.0);
1901 1901
1902 // Send the correct number of frames that the physics library 1902 // Send the correct number of frames that the physics library
1903 // has processed to the stats reporter 1903 // has processed to the stats reporter
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 0a1a226..866a43c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2672,20 +2672,27 @@ namespace OpenSim.Region.Framework.Scenes
2672 } 2672 }
2673 else 2673 else
2674 { 2674 {
2675 //NonPhysicalGrabMovement(pos); 2675 NonPhysicalGrabMovement(pos);
2676 } 2676 }
2677 } 2677 }
2678 else 2678 else
2679 { 2679 {
2680 //NonPhysicalGrabMovement(pos); 2680 NonPhysicalGrabMovement(pos);
2681 } 2681 }
2682 } 2682 }
2683 } 2683 }
2684 2684
2685 /// <summary>
2686 /// Apply possition for grabbing non-physical linksets (Ctrl+Drag)
2687 /// This MUST be blocked for linksets that contain touch scripts because the viewer triggers grab on the touch
2688 /// event (Viewer Bug?) This would allow anyone to drag a linkset with a touch script. SL behaviour is also to
2689 /// block grab on prims with touch events.
2690 /// </summary>
2691 /// <param name="pos">New Position</param>
2685 public void NonPhysicalGrabMovement(Vector3 pos) 2692 public void NonPhysicalGrabMovement(Vector3 pos)
2686 { 2693 {
2687 AbsolutePosition = pos; 2694 if(!IsAttachment && ScriptCount() == 0)
2688 m_rootPart.SendTerseUpdateToAllClients(); 2695 UpdateGroupPosition(pos);
2689 } 2696 }
2690 2697
2691 /// <summary> 2698 /// <summary>
@@ -2781,17 +2788,28 @@ namespace OpenSim.Region.Framework.Scenes
2781 } 2788 }
2782 else 2789 else
2783 { 2790 {
2784 //NonPhysicalSpinMovement(pos); 2791 NonPhysicalSpinMovement(newOrientation);
2785 } 2792 }
2786 } 2793 }
2787 else 2794 else
2788 { 2795 {
2789 //NonPhysicalSpinMovement(pos); 2796 NonPhysicalSpinMovement(newOrientation);
2790 } 2797 }
2791 } 2798 }
2792 } 2799 }
2793 2800
2794 /// <summary> 2801 /// <summary>
2802 /// Apply rotation for spinning non-physical linksets (Ctrl+Shift+Drag)
2803 /// As with dragging, scripted objects must be blocked from spinning
2804 /// </summary>
2805 /// <param name="newOrientation">New Rotation</param>
2806 private void NonPhysicalSpinMovement(Quaternion newOrientation)
2807 {
2808 if(!IsAttachment && ScriptCount() == 0)
2809 UpdateGroupRotationR(newOrientation);
2810 }
2811
2812 /// <summary>
2795 /// Set the name of a prim 2813 /// Set the name of a prim
2796 /// </summary> 2814 /// </summary>
2797 /// <param name="name"></param> 2815 /// <param name="name"></param>
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs
new file mode 100644
index 0000000..927d8e8
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs
@@ -0,0 +1,136 @@
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 System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using System.Xml;
33using System.Linq;
34using Nini.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Serialization.External;
39using OpenSim.Framework.Communications;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Scenes.Serialization;
42using OpenSim.Services.Interfaces;
43using OpenSim.Tests.Common;
44
45namespace OpenSim.Region.Framework.Scenes.Tests
46{
47 /// <summary>
48 /// Basic scene object serialization tests.
49 /// </summary>
50 [TestFixture]
51 public class SceneObjectSerializationTests : OpenSimTestCase
52 {
53
54 /// <summary>
55 /// Serialize and deserialize.
56 /// </summary>
57 [Test]
58 public void TestSerialDeserial()
59 {
60 TestHelpers.InMethod();
61
62 Scene scene = new SceneHelpers().SetupScene();
63 int partsToTestCount = 3;
64
65 SceneObjectGroup so
66 = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
67 SceneObjectPart[] parts = so.Parts;
68 so.Name = "obj1";
69 so.Description = "xpto";
70
71 string xml = SceneObjectSerializer.ToXml2Format(so);
72 Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string");
73
74 XmlDocument doc = new XmlDocument();
75 doc.LoadXml(xml);
76 XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart");
77 Assert.That(nodes.Count, Is.EqualTo(3), "SOG serialization resulted in wrong number of SOPs");
78
79 SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml);
80 Assert.IsNotNull(so2, "SOG deserialization resulted in null object");
81 Assert.That(so2.Name == so.Name, "Name of deserialized object does not match original name");
82 Assert.That(so2.Description == so.Description, "Description of deserialized object does not match original name");
83 }
84
85 /// <summary>
86 /// This checks for a bug reported in mantis #7514
87 /// </summary>
88 [Test]
89 public void TestNamespaceAttribute()
90 {
91 TestHelpers.InMethod();
92
93 Scene scene = new SceneHelpers().SetupScene();
94 UserAccount account = new UserAccount(UUID.Zero, UUID.Random(), "Test", "User", string.Empty);
95 scene.UserAccountService.StoreUserAccount(account);
96 int partsToTestCount = 1;
97
98 SceneObjectGroup so
99 = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
100 SceneObjectPart[] parts = so.Parts;
101 so.Name = "obj1";
102 so.Description = "xpto";
103 so.OwnerID = account.PrincipalID;
104 so.RootPart.CreatorID = so.OwnerID;
105
106 string xml = SceneObjectSerializer.ToXml2Format(so);
107 Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string");
108
109 xml = ExternalRepresentationUtils.RewriteSOP(xml, "Test Scene", "http://localhost", scene.UserAccountService, UUID.Zero);
110 //Console.WriteLine(xml);
111
112 XmlDocument doc = new XmlDocument();
113 doc.LoadXml(xml);
114
115 XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart");
116 Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no SOPs");
117 foreach (XmlAttribute a in nodes[0].Attributes)
118 {
119 int count = a.Name.Count(c => c == ':');
120 Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in SOP");
121 }
122 nodes = doc.GetElementsByTagName("CreatorData");
123 Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no CreatorData");
124 foreach (XmlAttribute a in nodes[0].Attributes)
125 {
126 int count = a.Name.Count(c => c == ':');
127 Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in CreatorData");
128 }
129
130 SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml);
131 Assert.IsNotNull(so2, "SOG deserialization resulted in null object");
132 Assert.AreNotEqual(so.RootPart.CreatorIdentification, so2.RootPart.CreatorIdentification, "RewriteSOP failed to transform CreatorData.");
133 Assert.That(so2.RootPart.CreatorIdentification.Contains("http://"), "RewriteSOP failed to add the homeURL to CreatorData");
134 }
135 }
136} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
index d028374..f8ad958 100644
--- a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.8.1.*")] 33[assembly: AssemblyVersion("0.8.2.*")]
34 34
35 35
36[assembly: Addin("OpenSim.Region.OptionalModules", OpenSim.VersionInfo.VersionNumber)] 36[assembly: Addin("OpenSim.Region.OptionalModules", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
index 28dc5f5..ceb3332 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
@@ -115,6 +115,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
115 115
116 private delegate T DefaultGetter<T>(string settingName, T defaultValue); 116 private delegate T DefaultGetter<T>(string settingName, T defaultValue);
117 private bool m_enabled; 117 private bool m_enabled;
118 private ICommandConsole m_console;
119 private List<Scene> m_Scenes = new List<Scene> ();
120
118 121
119 /// <summary> 122 /// <summary>
120 /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState! 123 /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
@@ -206,8 +209,20 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
206 /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded. 209 /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded.
207 /// </summary> 210 /// </summary>
208 /// <param name="scene"></param> 211 /// <param name="scene"></param>
209 void IRegionModuleBase.AddRegion(Scene scene) 212 void IRegionModuleBase.AddRegion (Scene scene)
210 { 213 {
214 if (!this.m_enabled) {
215 return;
216 }
217 lock (m_Scenes) {
218 m_Scenes.Add (scene);
219 }
220 m_console = MainConsole.Instance;
221
222 m_console.Commands.AddCommand (
223 "AutoBackup", false, "dobackup",
224 "dobackup",
225 "do backup.", DoBackup);
211 } 226 }
212 227
213 /// <summary> 228 /// <summary>
@@ -220,7 +235,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
220 { 235 {
221 return; 236 return;
222 } 237 }
223 238 m_Scenes.Remove (scene);
224 if (this.m_states.ContainsKey(scene)) 239 if (this.m_states.ContainsKey(scene))
225 { 240 {
226 AutoBackupModuleState abms = this.m_states[scene]; 241 AutoBackupModuleState abms = this.m_states[scene];
@@ -275,6 +290,28 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
275 290
276 #endregion 291 #endregion
277 292
293 private void DoBackup (string module, string[] args)
294 {
295 if (args.Length != 2) {
296 MainConsole.Instance.OutputFormat ("Usage: dobackup <regionname>");
297 return;
298 }
299 bool found = false;
300 string name = args [1];
301 lock (m_Scenes) {
302 foreach (Scene s in m_Scenes) {
303 string test = s.Name.ToString ();
304 if (test == name) {
305 found = true;
306 DoRegionBackup (s);
307 }
308 }
309 if (!found) {
310 MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name);
311 }
312 }
313 }
314
278 /// <summary> 315 /// <summary>
279 /// Set up internal state for a given scene. Fairly complex code. 316 /// Set up internal state for a given scene. Fairly complex code.
280 /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene. 317 /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene.
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
index eba0675..7d054dd 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.8.1.*")] 58[assembly : AssemblyVersion("0.8.2.*")]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
index 4de5b47..4f90eee 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
index 1486ba8..c5867b2 100644
--- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
32// You can specify all the values or you can default the Build and Revision Numbers 32// You can specify all the values or you can default the Build and Revision Numbers
33// by using the '*' as shown below: 33// by using the '*' as shown below:
34// [assembly: AssemblyVersion("1.0.*")] 34// [assembly: AssemblyVersion("1.0.*")]
35[assembly: AssemblyVersion("0.8.1.*")] 35[assembly: AssemblyVersion("0.8.2.*")]
36 36
diff --git a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
index 202ef20..33f60e4 100644
--- a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.8.1.*")] 58[assembly : AssemblyVersion("0.8.2.*")]
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index d96de4a..42231b5 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -84,7 +84,8 @@ namespace OpenSim.Region.Physics.Meshing
84 private List<List<Vector3>> mConvexHulls = null; 84 private List<List<Vector3>> mConvexHulls = null;
85 private List<Vector3> mBoundingHull = null; 85 private List<Vector3> mBoundingHull = null;
86 86
87 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); 87 // Mesh cache. Static so it can be shared across instances of this class
88 private static Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
88 89
89 public Meshmerizer(IConfigSource config) 90 public Meshmerizer(IConfigSource config)
90 { 91 {
@@ -927,8 +928,11 @@ namespace OpenSim.Region.Physics.Meshing
927 if (shouldCache) 928 if (shouldCache)
928 { 929 {
929 key = primShape.GetMeshKey(size, lod); 930 key = primShape.GetMeshKey(size, lod);
930 if (m_uniqueMeshes.TryGetValue(key, out mesh)) 931 lock (m_uniqueMeshes)
931 return mesh; 932 {
933 if (m_uniqueMeshes.TryGetValue(key, out mesh))
934 return mesh;
935 }
932 } 936 }
933 937
934 if (size.X < 0.01f) size.X = 0.01f; 938 if (size.X < 0.01f) size.X = 0.01f;
@@ -954,7 +958,10 @@ namespace OpenSim.Region.Physics.Meshing
954 958
955 if (shouldCache) 959 if (shouldCache)
956 { 960 {
957 m_uniqueMeshes.Add(key, mesh); 961 lock (m_uniqueMeshes)
962 {
963 m_uniqueMeshes.Add(key, mesh);
964 }
958 } 965 }
959 } 966 }
960 967
diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
index 2b083fe..ec968c0 100644
--- a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
index b95f7f4..076da78 100644
--- a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.8.1.*")] 58[assembly : AssemblyVersion("0.8.2.*")]
diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
index 125d38a..fc1ffba 100644
--- a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.8.1.*")] 58[assembly : AssemblyVersion("0.8.2.*")]
diff --git a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
index e8b29f9..11b89d2 100644
--- a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.8.1.*")] 33[assembly: AssemblyVersion("0.8.2.*")]
34 34
35[assembly: Addin("OpenSim.RegionModules.RegionCombinerModule", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.RegionModules.RegionCombinerModule", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] 36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 40b7c35..089a5a8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Imaging;
31using System.Runtime.Remoting.Lifetime; 33using System.Runtime.Remoting.Lifetime;
32using System.Text; 34using System.Text;
33using System.Threading; 35using System.Threading;
@@ -35,7 +37,9 @@ using System.Text.RegularExpressions;
35using Nini.Config; 37using Nini.Config;
36using log4net; 38using log4net;
37using OpenMetaverse; 39using OpenMetaverse;
40using OpenMetaverse.Assets;
38using OpenMetaverse.Packets; 41using OpenMetaverse.Packets;
42using OpenMetaverse.Rendering;
39using OpenSim; 43using OpenSim;
40using OpenSim.Framework; 44using OpenSim.Framework;
41 45
@@ -182,6 +186,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
182 protected bool m_restrictEmail = false; 186 protected bool m_restrictEmail = false;
183 protected ISoundModule m_SoundModule = null; 187 protected ISoundModule m_SoundModule = null;
184 188
189 protected float m_avatarHeightCorrection = 0.2f;
190 protected bool m_useSimpleBoxesInGetBoundingBox = false;
191 protected bool m_addStatsInGetBoundingBox = false;
192
193 //LSL Avatar Bounding Box (lABB), lower (1) and upper (2),
194 //standing (Std), Groundsitting (Grs), Sitting (Sit),
195 //along X, Y and Z axes, constants (0) and coefficients (1)
196 protected float m_lABB1StdX0 = -0.275f;
197 protected float m_lABB2StdX0 = 0.275f;
198 protected float m_lABB1StdY0 = -0.35f;
199 protected float m_lABB2StdY0 = 0.35f;
200 protected float m_lABB1StdZ0 = -0.1f;
201 protected float m_lABB1StdZ1 = -0.5f;
202 protected float m_lABB2StdZ0 = 0.1f;
203 protected float m_lABB2StdZ1 = 0.5f;
204 protected float m_lABB1GrsX0 = -0.3875f;
205 protected float m_lABB2GrsX0 = 0.3875f;
206 protected float m_lABB1GrsY0 = -0.5f;
207 protected float m_lABB2GrsY0 = 0.5f;
208 protected float m_lABB1GrsZ0 = -0.05f;
209 protected float m_lABB1GrsZ1 = -0.375f;
210 protected float m_lABB2GrsZ0 = 0.5f;
211 protected float m_lABB2GrsZ1 = 0.0f;
212 protected float m_lABB1SitX0 = -0.5875f;
213 protected float m_lABB2SitX0 = 0.1875f;
214 protected float m_lABB1SitY0 = -0.35f;
215 protected float m_lABB2SitY0 = 0.35f;
216 protected float m_lABB1SitZ0 = -0.35f;
217 protected float m_lABB1SitZ1 = -0.375f;
218 protected float m_lABB2SitZ0 = -0.25f;
219 protected float m_lABB2SitZ1 = 0.25f;
220
221 protected float m_primSafetyCoeffX = 2.414214f;
222 protected float m_primSafetyCoeffY = 2.414214f;
223 protected float m_primSafetyCoeffZ = 1.618034f;
224 protected bool m_useCastRayV3 = false;
225 protected float m_floatToleranceInCastRay = 0.000001f;
226 protected float m_floatTolerance2InCastRay = 0.0001f;
227 protected DetailLevel m_primLodInCastRay = DetailLevel.Medium;
228 protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium;
229 protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest;
230 protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium;
231 protected int m_maxHitsInCastRay = 16;
232 protected int m_maxHitsPerPrimInCastRay = 16;
233 protected int m_maxHitsPerObjectInCastRay = 16;
234 protected bool m_detectExitsInCastRay = false;
235 protected bool m_filterPartsInCastRay = false;
236 protected bool m_doAttachmentsInCastRay = false;
237
185 //An array of HTTP/1.1 headers that are not allowed to be used 238 //An array of HTTP/1.1 headers that are not allowed to be used
186 //as custom headers by llHTTPRequest. 239 //as custom headers by llHTTPRequest.
187 private string[] HttpStandardHeaders = 240 private string[] HttpStandardHeaders =
@@ -257,6 +310,49 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
257 if (lslConfig != null) 310 if (lslConfig != null)
258 { 311 {
259 m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); 312 m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail);
313 m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection);
314 m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox);
315 m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox);
316 m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0);
317 m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0);
318 m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0);
319 m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0);
320 m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0);
321 m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1);
322 m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0);
323 m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1);
324 m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0);
325 m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0);
326 m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0);
327 m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0);
328 m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0);
329 m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1);
330 m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0);
331 m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1);
332 m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0);
333 m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0);
334 m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0);
335 m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0);
336 m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0);
337 m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1);
338 m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0);
339 m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1);
340 m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX);
341 m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY);
342 m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ);
343 m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3);
344 m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay);
345 m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay);
346 m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay);
347 m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay);
348 m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay);
349 m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay);
350 m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay);
351 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
352 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
353 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
354 m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
355 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
260 } 356 }
261 357
262 IConfig smtpConfig = seConfigSource.Configs["SMTP"]; 358 IConfig smtpConfig = seConfigSource.Configs["SMTP"];
@@ -7725,13 +7821,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7725 { 7821 {
7726 profilecut.y = 1f; 7822 profilecut.y = 1f;
7727 } 7823 }
7728 if (profilecut.y - profilecut.x < 0.05f) 7824 if (profilecut.y - profilecut.x < 0.02f)
7729 { 7825 {
7730 profilecut.x = profilecut.y - 0.05f; 7826 profilecut.x = profilecut.y - 0.02f;
7731 if (profilecut.x < 0.0f) 7827 if (profilecut.x < 0.0f)
7732 { 7828 {
7733 profilecut.x = 0.0f; 7829 profilecut.x = 0.0f;
7734 profilecut.y = 0.05f; 7830 profilecut.y = 0.02f;
7735 } 7831 }
7736 } 7832 }
7737 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); 7833 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
@@ -9584,80 +9680,441 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9584 } 9680 }
9585 9681
9586 /// <summary> 9682 /// <summary>
9587 /// A partial implementation. 9683 /// Full implementation of llGetBoundingBox according to SL 2015-04-15.
9684 /// http://wiki.secondlife.com/wiki/LlGetBoundingBox
9588 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox 9685 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
9589 /// So far only valid for standing/flying/ground sitting avatars and single prim objects. 9686 /// Returns local bounding box of avatar without attachments
9590 /// If the object has multiple prims and/or a sitting avatar then the bounding 9687 /// if target is non-seated avatar or prim/mesh in avatar attachment.
9591 /// box is for the root prim only. 9688 /// Returns local bounding box of object including seated avatars
9689 /// if target is seated avatar or prim/mesh in object.
9690 /// Uses meshing of prims for high accuracy
9691 /// or less accurate box models for speed.
9592 /// </summary> 9692 /// </summary>
9593 public LSL_List llGetBoundingBox(string obj) 9693 public LSL_List llGetBoundingBox(string obj)
9594 { 9694 {
9595 m_host.AddScriptLPS(1); 9695 m_host.AddScriptLPS(1);
9696
9697 // Get target avatar if non-seated avatar or attachment, or prim and object
9596 UUID objID = UUID.Zero; 9698 UUID objID = UUID.Zero;
9699 UUID.TryParse(obj, out objID);
9700 ScenePresence agent = World.GetScenePresence(objID);
9701 if (agent != null)
9702 {
9703 if (agent.ParentPart != null)
9704 {
9705 objID = agent.ParentPart.UUID;
9706 agent = null;
9707 }
9708 }
9709 SceneObjectGroup group = null;
9710 SceneObjectPart target = World.GetSceneObjectPart(objID);
9711 if (target != null)
9712 {
9713 group = target.ParentGroup;
9714 if (group.IsAttachment) {
9715 objID = group.AttachedAvatar;
9716 agent = World.GetScenePresence(objID);
9717 group = null;
9718 target = null;
9719 }
9720 }
9721
9722 // Initialize but break if no target
9597 LSL_List result = new LSL_List(); 9723 LSL_List result = new LSL_List();
9598 if (!UUID.TryParse(obj, out objID)) 9724 int groupCount = 0;
9725 int partCount = 0;
9726 int vertexCount = 0;
9727 if (target == null && agent == null)
9599 { 9728 {
9600 result.Add(new LSL_Vector()); 9729 result.Add(new LSL_Vector());
9601 result.Add(new LSL_Vector()); 9730 result.Add(new LSL_Vector());
9731 if (m_addStatsInGetBoundingBox)
9732 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9602 return result; 9733 return result;
9603 } 9734 }
9604 ScenePresence presence = World.GetScenePresence(objID); 9735 Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
9605 if (presence != null) 9736 Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue);
9737
9738 // Try to get a mesher
9739 IRendering primMesher = null;
9740 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
9741 if (renderers.Count > 0)
9742 primMesher = RenderingLoader.LoadRenderer(renderers[0]);
9743
9744 // Get bounding box of just avatar, seated or not
9745 if (agent != null)
9746 {
9747 bool hasParent = false;
9748 Vector3 lower;
9749 Vector3 upper;
9750 BoundingBoxOfScenePresence(agent, out lower, out upper);
9751 Vector3 offset = Vector3.Zero;
9752
9753 // Since local bounding box unrotated and untilted, keep it simple
9754 AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9755 partCount++;
9756 groupCount++;
9757
9758 // Return lower and upper bounding box corners
9759 result.Add(new LSL_Vector(minPosition));
9760 result.Add(new LSL_Vector(maxPosition));
9761 if (m_addStatsInGetBoundingBox)
9762 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9763 return result;
9764 }
9765 // Get bounding box of object including seated avatars
9766 else if (group != null)
9606 { 9767 {
9607 if (presence.ParentID == 0) // not sat on an object 9768 // Merge bounding boxes of all parts (prims and mesh)
9769 foreach (SceneObjectPart part in group.Parts)
9608 { 9770 {
9609 LSL_Vector lower; 9771 bool hasParent = (!part.IsRoot);
9610 LSL_Vector upper; 9772 // When requested or if no mesher, keep it simple
9611 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID 9773 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
9612 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
9613 { 9774 {
9614 // This is for ground sitting avatars 9775 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9615 float height = presence.Appearance.AvatarHeight / 2.66666667f;
9616 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
9617 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
9618 } 9776 }
9777 // Do the full mounty
9619 else 9778 else
9620 { 9779 {
9621 // This is for standing/flying avatars 9780 Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset);
9622 float height = presence.Appearance.AvatarHeight / 2.0f; 9781 byte[] sculptAsset = null;
9623 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); 9782 if (omvPrim.Sculpt != null)
9624 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); 9783 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
9784
9785 // When part is mesh
9786 // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler.
9787 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
9788 {
9789 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
9790 FacetedMesh mesh = null;
9791 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh);
9792 meshAsset = null;
9793 if (mesh != null)
9794 {
9795 AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9796 mesh = null;
9797 }
9798 }
9799
9800 // When part is sculpt
9801 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
9802 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
9803 {
9804 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
9805 if (imgDecoder != null)
9806 {
9807 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
9808 if (sculpt != null)
9809 {
9810 SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium);
9811 sculpt.Dispose();
9812 if (mesh != null)
9813 {
9814 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9815 mesh = null;
9816 }
9817 }
9818 }
9819 }
9820
9821 // When part is prim
9822 else if (omvPrim.Sculpt == null)
9823 {
9824 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9825 if (mesh != null)
9826 {
9827 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9828 mesh = null;
9829 }
9830 }
9831
9832 // When all else fails, try fallback to simple box
9833 else
9834 {
9835 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9836 }
9625 } 9837 }
9626 result.Add(lower); 9838 partCount++;
9627 result.Add(upper);
9628 return result;
9629 } 9839 }
9840 }
9841
9842 // Merge bounding boxes of seated avatars
9843 foreach (ScenePresence sp in group.GetSittingAvatars())
9844 {
9845 Vector3 lower;
9846 Vector3 upper;
9847 BoundingBoxOfScenePresence(sp, out lower, out upper);
9848 Vector3 offset = sp.OffsetPosition;
9849
9850 bool hasParent = true;
9851 // When requested or if no mesher, keep it simple
9852 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
9853 {
9854 AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9855 }
9856 // Do the full mounty
9630 else 9857 else
9631 { 9858 {
9632 // sitting on an object so we need the bounding box of that 9859 // Prim shapes don't do center offsets, so add it here.
9633 // which should include the avatar so set the UUID to the 9860 offset = offset + (lower + upper) * 0.5f * sp.Rotation;
9634 // UUID of the object the avatar is sat on and allow it to fall through 9861 Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE);
9635 // to processing an object 9862 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9636 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID); 9863 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9637 objID = p.UUID; 9864 mesh = null;
9638 } 9865 }
9866 partCount++;
9867 }
9868
9869 groupCount++;
9870
9871 // Return lower and upper bounding box corners
9872 result.Add(new LSL_Vector(minPosition));
9873 result.Add(new LSL_Vector(maxPosition));
9874 if (m_addStatsInGetBoundingBox)
9875 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9876
9877 primMesher = null;
9878 return result;
9879 }
9880
9881 /// <summary>
9882 /// Helper to calculate bounding box of an avatar.
9883 /// </summary>
9884 private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper)
9885 {
9886 // Adjust from OS model
9887 // avatar height = visual height - 0.2, bounding box height = visual height
9888 // to SL model
9889 // avatar height = visual height, bounding box height = visual height + 0.2
9890 float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection;
9891
9892 // According to avatar bounding box in SL 2015-04-18:
9893 // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h>
9894 // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5>
9895 // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h>
9896
9897 // When avatar is sitting
9898 if (sp.ParentPart != null)
9899 {
9900 lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height);
9901 upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height);
9639 } 9902 }
9640 SceneObjectPart part = World.GetSceneObjectPart(objID); 9903 // When avatar is groundsitting
9641 // Currently only works for single prims without a sitting avatar 9904 else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
9642 if (part != null)
9643 { 9905 {
9644 Vector3 halfSize = part.Scale / 2.0f; 9906 lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height);
9645 LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; 9907 upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height);
9646 LSL_Vector upper = new LSL_Vector(halfSize);
9647 result.Add(lower);
9648 result.Add(upper);
9649 return result;
9650 } 9908 }
9909 // When avatar is standing or flying
9910 else
9911 {
9912 lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height);
9913 upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height);
9914 }
9915 }
9651 9916
9652 // Not found so return empty values 9917 /// <summary>
9653 result.Add(new LSL_Vector()); 9918 /// Helper to approximate a part with a simple box.
9654 result.Add(new LSL_Vector()); 9919 /// </summary>
9655 return result; 9920 private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9921 {
9922 // Parse the 8 box corners
9923 for (int i = 0; i < 8; i++)
9924 {
9925 // Calculate each box corner
9926 Vector3 position = corner1;
9927 if ((i & 1) != 0)
9928 position.X = corner2.X;
9929 if ((i & 2) != 0)
9930 position.Y = corner2.Y;
9931 if ((i & 4) != 0)
9932 position.Z = corner2.Z;
9933 // Rotate part unless part is root
9934 if (hasParent)
9935 position = position * rotation;
9936 position = position + offset;
9937 // Adjust lower and upper bounding box corners if needed
9938 lower = Vector3.Min(lower, position);
9939 upper = Vector3.Max(upper, position);
9940 count++;
9941 }
9656 } 9942 }
9657 9943
9944 /// <summary>
9945 /// Helper to parse a meshed prim and needed especially
9946 /// for accuracy with tortured prims and sculpts.
9947 /// </summary>
9948 private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9949 {
9950 // Quirk: A meshed box contains 10 instead of the 8 necessary vertices.
9951 if (mesh != null)
9952 {
9953 // Parse each vertex in mesh
9954 foreach (Vertex vertex in mesh.Vertices)
9955 {
9956 Vector3 position = vertex.Position;
9957 position = position * prim.Scale;
9958 // Rotate part unless part is root
9959 if (hasParent)
9960 position = position * prim.Rotation;
9961 position = position + prim.Position;
9962 // Adjust lower and upper bounding box corners if needed
9963 lower = Vector3.Min(lower, position);
9964 upper = Vector3.Max(upper, position);
9965 count++;
9966 }
9967 }
9968 }
9969
9970 /// <summary>
9971 /// Helper to parse mesh because no method exists
9972 /// to parse mesh assets to SimpleMesh.
9973 /// </summary>
9974 private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9975 {
9976 if (mesh != null)
9977 {
9978 // Parse each face in mesh
9979 // since vertex array isn't populated.
9980 // This parses each unique vertex 3-6 times.
9981 foreach (Face face in mesh.Faces)
9982 {
9983 // Parse each vertex in face
9984 foreach (Vertex vertex in face.Vertices)
9985 {
9986 Vector3 position = vertex.Position;
9987 position = position * prim.Scale;
9988 // Rotate part unless part is root
9989 if (hasParent)
9990 position = position * prim.Rotation;
9991 position = position + prim.Position;
9992 // Adjust lower and upper bounding box corners if needed
9993 lower = Vector3.Min(lower, position);
9994 upper = Vector3.Max(upper, position);
9995 count++;
9996 }
9997 }
9998 }
9999 }
10000
10001 /// <summary>
10002 /// Helper to make up an OpenMetaverse prim
10003 /// needed to create mesh from parts.
10004 /// </summary>
10005 private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType)
10006 {
10007 // Initialize and set common parameters
10008 Primitive prim = new OpenMetaverse.Primitive();
10009 prim.Scale = scale;
10010 prim.Position = position;
10011 prim.Rotation = rotation;
10012 prim.PrimData.PathShearX = 0.0f;
10013 prim.PrimData.PathShearY = 0.0f;
10014 prim.PrimData.PathBegin = 0.0f;
10015 prim.PrimData.PathEnd = 1.0f;
10016 prim.PrimData.PathScaleX = 1.0f;
10017 prim.PrimData.PathScaleY = 1.0f;
10018 prim.PrimData.PathTaperX = 0.0f;
10019 prim.PrimData.PathTaperY = 0.0f;
10020 prim.PrimData.PathTwistBegin = 0.0f;
10021 prim.PrimData.PathTwist = 0.0f;
10022 prim.PrimData.ProfileBegin = 0.0f;
10023 prim.PrimData.ProfileEnd = 1.0f;
10024 prim.PrimData.ProfileHollow = 0.0f;
10025 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10026 prim.PrimData.ProfileHole = (HoleType)0;
10027 prim.PrimData.PathCurve = (PathCurve)16;
10028 prim.PrimData.PathRadiusOffset = 0.0f;
10029 prim.PrimData.PathRevolutions = 1.0f;
10030 prim.PrimData.PathSkew = 0.0f;
10031 prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
10032 prim.PrimData.State = (byte)0;
10033
10034 // Set type specific parameters
10035 switch (primType)
10036 {
10037 // Set specific parameters for box
10038 case ScriptBaseClass.PRIM_TYPE_BOX:
10039 prim.PrimData.PathScaleY = 1.0f;
10040 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10041 prim.PrimData.PathCurve = (PathCurve)16;
10042 break;
10043 // Set specific parameters for cylinder
10044 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
10045 prim.PrimData.PathScaleY = 1.0f;
10046 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10047 prim.PrimData.PathCurve = (PathCurve)16;
10048 break;
10049 // Set specific parameters for prism
10050 case ScriptBaseClass.PRIM_TYPE_PRISM:
10051 prim.PrimData.PathScaleY = 1.0f;
10052 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10053 prim.PrimData.PathCurve = (PathCurve)16;
10054 break;
10055 // Set specific parameters for sphere
10056 case ScriptBaseClass.PRIM_TYPE_SPHERE:
10057 prim.PrimData.PathScaleY = 1.0f;
10058 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10059 prim.PrimData.PathCurve = (PathCurve)32;
10060 break;
10061 // Set specific parameters for torus
10062 case ScriptBaseClass.PRIM_TYPE_TORUS:
10063 prim.PrimData.PathScaleY = 0.5f;
10064 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10065 prim.PrimData.PathCurve = (PathCurve)32;
10066 break;
10067 // Set specific parameters for tube
10068 case ScriptBaseClass.PRIM_TYPE_TUBE:
10069 prim.PrimData.PathScaleY = 0.5f;
10070 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10071 prim.PrimData.PathCurve = (PathCurve)32;
10072 break;
10073 // Set specific parameters for ring
10074 case ScriptBaseClass.PRIM_TYPE_RING:
10075 prim.PrimData.PathScaleY = 0.5f;
10076 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10077 prim.PrimData.PathCurve = (PathCurve)32;
10078 break;
10079 // Set specific parameters for sculpt
10080 case ScriptBaseClass.PRIM_TYPE_SCULPT:
10081 prim.PrimData.PathScaleY = 1.0f;
10082 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10083 prim.PrimData.PathCurve = (PathCurve)32;
10084 break;
10085 // Default to specific parameters for box
10086 default:
10087 prim.PrimData.PathScaleY = 1.0f;
10088 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10089 prim.PrimData.PathCurve = (PathCurve)16;
10090 break;
10091 }
10092
10093 return prim;
10094 }
10095
10096 /// <summary>
10097 /// Implementation of llGetGeometricCenter according to SL 2015-04-30.
10098 /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter
10099 /// Returns the average position offset of all linked parts,
10100 /// including the root prim and seated avatars,
10101 /// relative to the root prim in local coordinates.
10102 /// </summary>
9658 public LSL_Vector llGetGeometricCenter() 10103 public LSL_Vector llGetGeometricCenter()
9659 { 10104 {
9660 return new LSL_Vector(m_host.GetGeometricCenter()); 10105 // Subtract whatever position the root prim has to make it zero
10106 Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f;
10107
10108 // Add all prim/part position offsets
10109 foreach (SceneObjectPart part in m_host.ParentGroup.Parts)
10110 offset = offset + part.OffsetPosition;
10111 // Add all avatar/scene presence position offsets
10112 foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars())
10113 offset = offset + sp.OffsetPosition;
10114
10115 // Calculate and return the average offset
10116 offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount());
10117 return new LSL_Vector(offset);
9661 } 10118 }
9662 10119
9663 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) 10120 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules)
@@ -12600,6 +13057,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12600 case ScriptBaseClass.OBJECT_TEMP_ON_REZ: 13057 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
12601 ret.Add(new LSL_Integer(0)); 13058 ret.Add(new LSL_Integer(0));
12602 break; 13059 break;
13060 case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13061 ret.Add(new LSL_Integer(-1));
13062 break;
13063 case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13064 ret.Add(new LSL_Float(0));
13065 break;
13066 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13067 LSL_Float shapeType;
13068 if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0)
13069 shapeType = new LSL_Float(1);
13070 else
13071 shapeType = new LSL_Float(0);
13072 ret.Add(shapeType);
13073 break;
13074 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13075 ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY));
13076 break;
12603 default: 13077 default:
12604 // Invalid or unhandled constant. 13078 // Invalid or unhandled constant.
12605 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 13079 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -12764,6 +13238,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12764 case ScriptBaseClass.OBJECT_TEMP_ON_REZ: 13238 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
12765 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); 13239 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0));
12766 break; 13240 break;
13241 case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13242 ret.Add(new LSL_Integer(0));
13243 break;
13244 case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13245 ret.Add(new LSL_Float(0));
13246 break;
13247 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13248 ret.Add(new LSL_Float(-1));
13249 break;
13250 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13251 ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString()));
13252 break;
12767 default: 13253 default:
12768 // Invalid or unhandled constant. 13254 // Invalid or unhandled constant.
12769 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 13255 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -13335,6 +13821,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13335 13821
13336 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 13822 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
13337 { 13823 {
13824 // Use llCastRay V3 if configured
13825 if (m_useCastRayV3)
13826 return llCastRayV3(start, end, options);
13827
13338 LSL_List list = new LSL_List(); 13828 LSL_List list = new LSL_List();
13339 13829
13340 m_host.AddScriptLPS(1); 13830 m_host.AddScriptLPS(1);
@@ -13524,6 +14014,732 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13524 return list; 14014 return list;
13525 } 14015 }
13526 14016
14017 /// <summary>
14018 /// Implementation of llCastRay similar to SL 2015-04-21.
14019 /// http://wiki.secondlife.com/wiki/LlCastRay
14020 /// Uses pure geometry, bounding shapes, meshing and no physics
14021 /// for prims, sculpts, meshes, avatars and terrain.
14022 /// Implements all flags, reject types and data flags.
14023 /// Can handle both objects/groups and prims/parts, by config.
14024 /// May sometimes be inaccurate owing to calculation precision,
14025 /// meshing detail level and a bug in libopenmetaverse PrimMesher.
14026 /// </summary>
14027 public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options)
14028 {
14029 // Initialize
14030 m_host.AddScriptLPS(1);
14031 List<RayHit> rayHits = new List<RayHit>();
14032 LSL_List result = new LSL_List();
14033 float tol = m_floatToleranceInCastRay;
14034 Vector3 pos1Ray = start;
14035 Vector3 pos2Ray = end;
14036
14037 // Get input options
14038 int rejectTypes = 0;
14039 int dataFlags = 0;
14040 int maxHits = 1;
14041 bool detectPhantom = false;
14042 for (int i = 0; i < options.Length; i += 2)
14043 {
14044 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
14045 rejectTypes = options.GetLSLIntegerItem(i + 1);
14046 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
14047 dataFlags = options.GetLSLIntegerItem(i + 1);
14048 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
14049 maxHits = options.GetLSLIntegerItem(i + 1);
14050 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
14051 detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0);
14052 }
14053 if (maxHits > m_maxHitsInCastRay)
14054 maxHits = m_maxHitsInCastRay;
14055 bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0);
14056 bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0);
14057 bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0);
14058 bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0);
14059 bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0);
14060 bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0);
14061 bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0);
14062
14063 // Calculate some basic parameters
14064 Vector3 vecRay = pos2Ray - pos1Ray;
14065 float rayLength = vecRay.Length();
14066
14067 // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits
14068 IRendering primMesher = null;
14069 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
14070 if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1)
14071 {
14072 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN));
14073 return result;
14074 }
14075 primMesher = RenderingLoader.LoadRenderer(renderers[0]);
14076
14077 // Iterate over all objects/groups and prims/parts in region
14078 World.ForEachSOG(
14079 delegate(SceneObjectGroup group)
14080 {
14081 // Check group filters unless part filters are configured
14082 bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical);
14083 bool isNonphysical = !isPhysical;
14084 bool isPhantom = group.IsPhantom || group.IsVolumeDetect;
14085 bool isAttachment = group.IsAttachment;
14086 bool doGroup = true;
14087 if (isPhysical && rejectPhysical)
14088 doGroup = false;
14089 if (isNonphysical && rejectNonphysical)
14090 doGroup = false;
14091 if (isPhantom && detectPhantom)
14092 doGroup = true;
14093 if (m_filterPartsInCastRay)
14094 doGroup = true;
14095 if (isAttachment && !m_doAttachmentsInCastRay)
14096 doGroup = false;
14097 // Parse object/group if passed filters
14098 if (doGroup)
14099 {
14100 // Iterate over all prims/parts in object/group
14101 foreach(SceneObjectPart part in group.Parts)
14102 {
14103 // Check part filters if configured
14104 if (m_filterPartsInCastRay)
14105 {
14106 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical);
14107 isNonphysical = !isPhysical;
14108 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive);
14109 bool doPart = true;
14110 if (isPhysical && rejectPhysical)
14111 doPart = false;
14112 if (isNonphysical && rejectNonphysical)
14113 doPart = false;
14114 if (isPhantom && detectPhantom)
14115 doPart = true;
14116 if (!doPart)
14117 continue;
14118 }
14119
14120 // Parse prim/part and project ray if passed filters
14121 Vector3 scalePart = part.Scale;
14122 Vector3 posPart = part.GetWorldPosition();
14123 Quaternion rotPart = part.GetWorldRotation();
14124 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14125 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14126 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14127
14128 // Filter parts by shape bounding boxes
14129 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
14130 if (!part.Shape.SculptEntry)
14131 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
14132 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
14133 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14134 {
14135 // Prepare data needed to check for ray hits
14136 RayTrans rayTrans = new RayTrans();
14137 rayTrans.PartId = part.UUID;
14138 rayTrans.GroupId = part.ParentGroup.UUID;
14139 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
14140 rayTrans.ScalePart = scalePart;
14141 rayTrans.PositionPart = posPart;
14142 rayTrans.RotationPart = rotPart;
14143 rayTrans.ShapeNeedsEnds = true;
14144 rayTrans.Position1Ray = pos1Ray;
14145 rayTrans.Position1RayProj = pos1RayProj;
14146 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14147
14148 // Make an OMV prim to be able to mesh part
14149 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart);
14150 byte[] sculptAsset = null;
14151 if (omvPrim.Sculpt != null)
14152 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
14153 FacetedMesh mesh = null;
14154
14155 // When part is mesh, get mesh and check for hits
14156 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
14157 {
14158 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
14159 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
14160 meshAsset = null;
14161 }
14162
14163 // When part is sculpt, create mesh and check for hits
14164 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
14165 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
14166 {
14167 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
14168 if (imgDecoder != null)
14169 {
14170 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
14171 if (sculpt != null)
14172 {
14173 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
14174 sculpt.Dispose();
14175 }
14176 }
14177 }
14178
14179 // When part is prim, create mesh and check for hits
14180 else if (omvPrim.Sculpt == null)
14181 {
14182 if (
14183 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
14184 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
14185 omvPrim.PrimData.PathSkew == 0.0 &&
14186 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
14187 )
14188 rayTrans.ShapeNeedsEnds = false;
14189 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
14190 }
14191
14192 // Check mesh for ray hits
14193 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14194 mesh = null;
14195 }
14196 }
14197 }
14198 }
14199 );
14200
14201 // Check avatar filter
14202 if (!rejectAgents)
14203 {
14204 // Iterate over all avatars in region
14205 World.ForEachRootScenePresence(
14206 delegate (ScenePresence sp)
14207 {
14208 // Get bounding box
14209 Vector3 lower;
14210 Vector3 upper;
14211 BoundingBoxOfScenePresence(sp, out lower, out upper);
14212 // Parse avatar
14213 Vector3 scalePart = upper - lower;
14214 Vector3 posPart = sp.AbsolutePosition;
14215 Quaternion rotPart = sp.GetWorldRotation();
14216 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14217 posPart = posPart + (lower + upper) * 0.5f * rotPart;
14218 // Project ray
14219 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14220 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14221
14222 // Filter avatars by shape bounding boxes
14223 Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol);
14224 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14225 {
14226 // Prepare data needed to check for ray hits
14227 RayTrans rayTrans = new RayTrans();
14228 rayTrans.PartId = sp.UUID;
14229 rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID;
14230 rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0;
14231 rayTrans.ScalePart = scalePart;
14232 rayTrans.PositionPart = posPart;
14233 rayTrans.RotationPart = rotPart;
14234 rayTrans.ShapeNeedsEnds = false;
14235 rayTrans.Position1Ray = pos1Ray;
14236 rayTrans.Position1RayProj = pos1RayProj;
14237 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14238
14239 // Make OMV prim, create and check mesh
14240 PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere();
14241 prim.Scale = scalePart;
14242 Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart);
14243 FacetedMesh mesh = primMesher.GenerateFacetedMesh(omvPrim, m_meshLodInCastRay);
14244 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14245 mesh = null;
14246 }
14247 }
14248 );
14249 }
14250
14251 // Check terrain filter
14252 if (!rejectLand)
14253 {
14254 // Parse terrain
14255
14256 // Mesh terrain and check bounding box
14257 Vector3 lower;
14258 Vector3 upper;
14259 List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper);
14260 lower.Z -= tol;
14261 upper.Z += tol;
14262 if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z))
14263 {
14264 // Prepare data needed to check for ray hits
14265 RayTrans rayTrans = new RayTrans();
14266 rayTrans.PartId = UUID.Zero;
14267 rayTrans.GroupId = UUID.Zero;
14268 rayTrans.Link = 0;
14269 rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f);
14270 rayTrans.PositionPart = Vector3.Zero;
14271 rayTrans.RotationPart = Quaternion.Identity;
14272 rayTrans.ShapeNeedsEnds = true;
14273 rayTrans.Position1Ray = pos1Ray;
14274 rayTrans.Position1RayProj = pos1Ray;
14275 rayTrans.VectorRayProj = vecRay;
14276
14277 // Check mesh
14278 AddRayInTris(triangles, rayTrans, ref rayHits);
14279 triangles = null;
14280 }
14281 }
14282
14283 // Sort hits by ascending distance
14284 rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance));
14285
14286 // Check excess hits per part and group
14287 for (int t = 0; t < 2; t++)
14288 {
14289 int maxHitsPerType = 0;
14290 UUID id = UUID.Zero;
14291 if (t == 0)
14292 maxHitsPerType = m_maxHitsPerPrimInCastRay;
14293 else
14294 maxHitsPerType = m_maxHitsPerObjectInCastRay;
14295
14296 // Handle excess hits only when needed
14297 if (maxHitsPerType < m_maxHitsInCastRay)
14298 {
14299 // Find excess hits
14300 Hashtable hits = new Hashtable();
14301 for (int i = rayHits.Count - 1; i >= 0; i--)
14302 {
14303 if (t == 0)
14304 id = rayHits[i].PartId;
14305 else
14306 id = rayHits[i].GroupId;
14307 if (hits.ContainsKey(id))
14308 hits[id] = (int)hits[id] + 1;
14309 else
14310 hits[id] = 1;
14311 }
14312
14313 // Remove excess hits
14314 for (int i = rayHits.Count - 1; i >= 0; i--)
14315 {
14316 if (t == 0)
14317 id = rayHits[i].PartId;
14318 else
14319 id = rayHits[i].GroupId;
14320 int hit = (int)hits[id];
14321 if (hit > m_maxHitsPerPrimInCastRay)
14322 {
14323 rayHits.RemoveAt(i);
14324 hit--;
14325 hits[id] = hit;
14326 }
14327 }
14328 }
14329 }
14330
14331 // Parse hits into result list according to data flags
14332 int hitCount = rayHits.Count;
14333 if (hitCount > maxHits)
14334 hitCount = maxHits;
14335 for (int i = 0; i < hitCount; i++)
14336 {
14337 RayHit rayHit = rayHits[i];
14338 if (getRootKey)
14339 result.Add(new LSL_Key(rayHit.GroupId.ToString()));
14340 else
14341 result.Add(new LSL_Key(rayHit.PartId.ToString()));
14342 result.Add(new LSL_Vector(rayHit.Position));
14343 if (getLinkNum)
14344 result.Add(new LSL_Integer(rayHit.Link));
14345 if (getNormal)
14346 result.Add(new LSL_Vector(rayHit.Normal));
14347 }
14348 result.Add(new LSL_Integer(hitCount));
14349 return result;
14350 }
14351
14352 /// <summary>
14353 /// Struct for transmitting parameters required for finding llCastRay ray hits.
14354 /// </summary>
14355 public struct RayTrans
14356 {
14357 public UUID PartId;
14358 public UUID GroupId;
14359 public int Link;
14360 public Vector3 ScalePart;
14361 public Vector3 PositionPart;
14362 public Quaternion RotationPart;
14363 public bool ShapeNeedsEnds;
14364 public Vector3 Position1Ray;
14365 public Vector3 Position1RayProj;
14366 public Vector3 VectorRayProj;
14367 }
14368
14369 /// <summary>
14370 /// Struct for llCastRay ray hits.
14371 /// </summary>
14372 public struct RayHit
14373 {
14374 public UUID PartId;
14375 public UUID GroupId;
14376 public int Link;
14377 public Vector3 Position;
14378 public Vector3 Normal;
14379 public float Distance;
14380 }
14381
14382 /// <summary>
14383 /// Helper to check if a ray intersects a shape bounding box.
14384 /// </summary>
14385 private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax)
14386 {
14387 // Skip if ray can't intersect bounding box;
14388 Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj);
14389 Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj);
14390 if (
14391 rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z ||
14392 rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z
14393 )
14394 return false;
14395
14396 // Check if ray intersect any bounding box side
14397 int sign = 0;
14398 float dist = 0.0f;
14399 Vector3 posProj = Vector3.Zero;
14400 Vector3 vecRayProj = pos2RayProj - pos1RayProj;
14401
14402 // Check both X sides unless ray is parallell to them
14403 if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay)
14404 {
14405 for (sign = -1; sign <= 1; sign += 2)
14406 {
14407 dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X;
14408 posProj = pos1RayProj + vecRayProj * dist;
14409 if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14410 return true;
14411 }
14412 }
14413
14414 // Check both Y sides unless ray is parallell to them
14415 if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay)
14416 {
14417 for (sign = -1; sign <= 1; sign += 2)
14418 {
14419 dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y;
14420 posProj = pos1RayProj + vecRayProj * dist;
14421 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14422 return true;
14423 }
14424 }
14425
14426 // Check both Z sides unless ray is parallell to them
14427 if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay)
14428 {
14429 for (sign = -1; sign <= 1; sign += 2)
14430 {
14431 dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z;
14432 posProj = pos1RayProj + vecRayProj * dist;
14433 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y)
14434 return true;
14435 }
14436 }
14437
14438 // No hits on bounding box so return false
14439 return false;
14440 }
14441
14442 /// <summary>
14443 /// Helper to parse FacetedMesh for ray hits.
14444 /// </summary>
14445 private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits)
14446 {
14447 if (mesh != null)
14448 {
14449 foreach (Face face in mesh.Faces)
14450 {
14451 for (int i = 0; i < face.Indices.Count; i += 3)
14452 {
14453 Tri triangle = new Tri();
14454 triangle.p1 = face.Vertices[face.Indices[i]].Position;
14455 triangle.p2 = face.Vertices[face.Indices[i + 1]].Position;
14456 triangle.p3 = face.Vertices[face.Indices[i + 2]].Position;
14457 AddRayInTri(triangle, rayTrans, ref rayHits);
14458 }
14459 }
14460 }
14461 }
14462
14463 /// <summary>
14464 /// Helper to parse Tri (triangle) List for ray hits.
14465 /// </summary>
14466 private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits)
14467 {
14468 foreach (Tri triangle in triangles)
14469 {
14470 AddRayInTri(triangle, rayTrans, ref rayHits);
14471 }
14472 }
14473
14474 /// <summary>
14475 /// Helper to add ray hit in a Tri (triangle).
14476 /// </summary>
14477 private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits)
14478 {
14479 // Check for hit in triangle
14480 Vector3 posHitProj;
14481 Vector3 normalProj;
14482 if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj))
14483 {
14484 // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center
14485 if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds)
14486 return;
14487
14488 // Transform hit and normal to region coordinate system
14489 Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart;
14490 Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart);
14491
14492 // Remove duplicate hits at triangle intersections
14493 float distance = Vector3.Distance(rayTrans.Position1Ray, posHit);
14494 for (int i = rayHits.Count - 1; i >= 0; i--)
14495 {
14496 if (rayHits[i].PartId != rayTrans.PartId)
14497 break;
14498 if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay)
14499 return;
14500 }
14501
14502 // Build result data set
14503 RayHit rayHit = new RayHit();
14504 rayHit.PartId = rayTrans.PartId;
14505 rayHit.GroupId = rayTrans.GroupId;
14506 rayHit.Link = rayTrans.Link;
14507 rayHit.Position = posHit;
14508 rayHit.Normal = normal;
14509 rayHit.Distance = distance;
14510 rayHits.Add(rayHit);
14511 }
14512 }
14513
14514 /// <summary>
14515 /// Helper to find ray hit in triangle
14516 /// </summary>
14517 bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj)
14518 {
14519 float tol = m_floatToleranceInCastRay;
14520 posHitProj = Vector3.Zero;
14521
14522 // Calculate triangle edge vectors
14523 Vector3 vec1Proj = triProj.p2 - triProj.p1;
14524 Vector3 vec2Proj = triProj.p3 - triProj.p2;
14525 Vector3 vec3Proj = triProj.p1 - triProj.p3;
14526
14527 // Calculate triangle normal
14528 normalProj = Vector3.Cross(vec1Proj, vec2Proj);
14529
14530 // Skip if degenerate triangle or ray parallell with triangle plane
14531 float divisor = Vector3.Dot(vecRayProj, normalProj);
14532 if (Math.Abs(divisor) < tol)
14533 return false;
14534
14535 // Skip if exit and not configured to detect
14536 if (divisor > tol && !m_detectExitsInCastRay)
14537 return false;
14538
14539 // Skip if outside ray ends
14540 float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor;
14541 if (distanceProj < -tol || distanceProj > 1 + tol)
14542 return false;
14543
14544 // Calculate hit position in triangle
14545 posHitProj = pos1RayProj + vecRayProj * distanceProj;
14546
14547 // Skip if outside triangle bounding box
14548 Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3);
14549 Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3);
14550 if (
14551 posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol ||
14552 posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol
14553 )
14554 return false;
14555
14556 // Skip if outside triangle
14557 if (
14558 Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol ||
14559 Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol ||
14560 Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol
14561 )
14562 return false;
14563
14564 // Return hit
14565 return true;
14566 }
14567
14568 /// <summary>
14569 /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box.
14570 /// </summary>
14571 private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper)
14572 {
14573 // Get bounding X-Y rectangle of terrain under ray
14574 lower = Vector3.Min(posStart, posEnd);
14575 upper = Vector3.Max(posStart, posEnd);
14576 lower.X = (float)Math.Floor(lower.X);
14577 lower.Y = (float)Math.Floor(lower.Y);
14578 float zLower = float.MaxValue;
14579 upper.X = (float)Math.Ceiling(upper.X);
14580 upper.Y = (float)Math.Ceiling(upper.Y);
14581 float zUpper = float.MinValue;
14582
14583 // Initialize Tri (triangle) List
14584 List<Tri> triangles = new List<Tri>();
14585
14586 // Set parsing lane direction to major ray X-Y axis
14587 Vector3 vec = posEnd - posStart;
14588 float xAbs = Math.Abs(vec.X);
14589 float yAbs = Math.Abs(vec.Y);
14590 bool bigX = true;
14591 if (yAbs > xAbs)
14592 {
14593 bigX = false;
14594 vec = vec / yAbs;
14595 }
14596 else if (xAbs > yAbs || xAbs > 0.0f)
14597 vec = vec / xAbs;
14598 else
14599 vec = new Vector3(1.0f, 1.0f, 0.0f);
14600
14601 // Simplify by start parsing in lower end of lane
14602 if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f))
14603 {
14604 Vector3 posTemp = posStart;
14605 posStart = posEnd;
14606 posEnd = posTemp;
14607 vec = vec * -1.0f;
14608 }
14609
14610 // First 1x1 rectangle under ray
14611 float xFloorOld = 0.0f;
14612 float yFloorOld = 0.0f;
14613 Vector3 pos = posStart;
14614 float xFloor = (float)Math.Floor(pos.X);
14615 float yFloor = (float)Math.Floor(pos.Y);
14616 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
14617
14618 // Parse every remaining 1x1 rectangle under ray
14619 while (pos != posEnd)
14620 {
14621 // Next 1x1 rectangle under ray
14622 xFloorOld = xFloor;
14623 yFloorOld = yFloor;
14624 pos = pos + vec;
14625
14626 // Clip position to 1x1 rectangle border
14627 xFloor = (float)Math.Floor(pos.X);
14628 yFloor = (float)Math.Floor(pos.Y);
14629 if (bigX && pos.X > xFloor)
14630 {
14631 pos.Y -= vec.Y * (pos.X - xFloor);
14632 pos.X = xFloor;
14633 }
14634 else if (!bigX && pos.Y > yFloor)
14635 {
14636 pos.X -= vec.X * (pos.Y - yFloor);
14637 pos.Y = yFloor;
14638 }
14639
14640 // Last 1x1 rectangle under ray
14641 if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y))
14642 {
14643 pos = posEnd;
14644 xFloor = (float)Math.Floor(pos.X);
14645 yFloor = (float)Math.Floor(pos.Y);
14646 }
14647
14648 // Add new 1x1 rectangle in lane
14649 if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld))
14650 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
14651 // Add last 1x1 rectangle in old lane at lane shift
14652 if (bigX && yFloor != yFloorOld)
14653 AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper);
14654 if (!bigX && xFloor != xFloorOld)
14655 AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper);
14656 }
14657
14658 // Finalize bounding box Z
14659 lower.Z = zLower;
14660 upper.Z = zUpper;
14661
14662 // Done and returning Tri (triangle)List
14663 return triangles;
14664 }
14665
14666 /// <summary>
14667 /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box.
14668 /// </summary>
14669 private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper)
14670 {
14671 int xInt = (int)xPos;
14672 int yInt = (int)yPos;
14673
14674 // Corner 1 of 1x1 rectangle
14675 int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
14676 int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
14677 Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14678 // Adjust bounding box
14679 zLower = Math.Min(zLower, pos1.Z);
14680 zUpper = Math.Max(zUpper, pos1.Z);
14681
14682 // Corner 2 of 1x1 rectangle
14683 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
14684 y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
14685 Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14686 // Adjust bounding box
14687 zLower = Math.Min(zLower, pos2.Z);
14688 zUpper = Math.Max(zUpper, pos2.Z);
14689
14690 // Corner 3 of 1x1 rectangle
14691 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
14692 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14693 Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14694 // Adjust bounding box
14695 zLower = Math.Min(zLower, pos3.Z);
14696 zUpper = Math.Max(zUpper, pos3.Z);
14697
14698 // Corner 4 of 1x1 rectangle
14699 x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
14700 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14701 Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14702 // Adjust bounding box
14703 zLower = Math.Min(zLower, pos4.Z);
14704 zUpper = Math.Max(zUpper, pos4.Z);
14705
14706 // Add triangle 1
14707 Tri triangle1 = new Tri();
14708 triangle1.p1 = pos1;
14709 triangle1.p2 = pos2;
14710 triangle1.p3 = pos3;
14711 triangles.Add(triangle1);
14712
14713 // Add triangle 2
14714 Tri triangle2 = new Tri();
14715 triangle2.p1 = pos3;
14716 triangle2.p2 = pos4;
14717 triangle2.p3 = pos1;
14718 triangles.Add(triangle2);
14719 }
14720
14721 /// <summary>
14722 /// Helper to get link number for a UUID.
14723 /// </summary>
14724 private int UUID2LinkNumber(SceneObjectPart part, UUID id)
14725 {
14726 SceneObjectGroup group = part.ParentGroup;
14727 if (group != null)
14728 {
14729 // Parse every link for UUID
14730 int linkCount = group.PrimCount + group.GetSittingAvatarsCount();
14731 for (int link = linkCount; link > 0; link--)
14732 {
14733 ISceneEntity entity = GetLinkEntity(part, link);
14734 // Return link number if UUID match
14735 if (entity != null && entity.UUID == id)
14736 return link;
14737 }
14738 }
14739 // Return link number 0 if no links or UUID matches
14740 return 0;
14741 }
14742
13527 public LSL_Integer llManageEstateAccess(int action, string avatar) 14743 public LSL_Integer llManageEstateAccess(int action, string avatar)
13528 { 14744 {
13529 m_host.AddScriptLPS(1); 14745 m_host.AddScriptLPS(1);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
index d02c91c..4708473 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index a96cd16..e37d3af 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -596,6 +596,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
596 public const int OBJECT_PHYSICS = 21; 596 public const int OBJECT_PHYSICS = 21;
597 public const int OBJECT_PHANTOM = 22; 597 public const int OBJECT_PHANTOM = 22;
598 public const int OBJECT_TEMP_ON_REZ = 23; 598 public const int OBJECT_TEMP_ON_REZ = 23;
599 public const int OBJECT_RENDER_WEIGHT = 24;
600 public const int OBJECT_HOVER_HEIGHT = 25;
601 public const int OBJECT_BODY_SHAPE_TYPE = 26;
602 public const int OBJECT_LAST_OWNER_ID = 27;
599 603
600 // Pathfinding types 604 // Pathfinding types
601 public const int OPT_OTHER = -1; 605 public const int OPT_OTHER = -1;
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
index 31acd44..4df09ef 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
index af7ee26..3eaaed0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
index 03612ef..0094af6 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.8.1.*")] 33[assembly: AssemblyVersion("0.8.2.*")]
34 34
35[assembly: Addin("OpenSim.Region.ScriptEngine.XEngine", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.Region.ScriptEngine.XEngine", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] 36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
index 58fa66f..9fac53e 100644
--- a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.8.1.*")] 32[assembly: AssemblyVersion("0.8.2.*")]
33 33