aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
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
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')
-rw-r--r--OpenSim/Addons/Groups/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs840
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs (renamed from OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescServerConnector.cs)0
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs (renamed from OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs)0
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs228
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs465
-rw-r--r--OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MySQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/Null/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Communications/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Console/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/InventoryCollection.cs4
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs184
-rw-r--r--OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs10
-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
-rw-r--r--OpenSim/Server/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs10
-rw-r--r--OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs110
-rw-r--r--OpenSim/Server/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs3
-rw-r--r--OpenSim/Services/AssetService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Connectors/Estate/EstateDataConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs125
-rw-r--r--OpenSim/Services/Connectors/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs31
-rw-r--r--OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs35
-rw-r--r--OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Friends/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/GridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/HypergridService/HGAssetService.cs2
-rw-r--r--OpenSim/Services/HypergridService/HGInstantMessageService.cs9
-rw-r--r--OpenSim/Services/HypergridService/HGInventoryService.cs9
-rw-r--r--OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Interfaces/IInventoryService.cs15
-rw-r--r--OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs48
-rw-r--r--OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tests/Clients/Grid/GridClient.cs205
-rw-r--r--OpenSim/Tests/Clients/Presence/OpenSim.Server.ini33
-rw-r--r--OpenSim/Tests/Clients/Presence/PresenceClient.cs115
-rw-r--r--OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini33
-rw-r--r--OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs144
-rw-r--r--OpenSim/Tests/Robust/Clients/Grid/GridClient.cs133
-rw-r--r--OpenSim/Tests/Robust/Clients/Grid/GridForm.html (renamed from OpenSim/Tests/Clients/Grid/GridForm.html)0
-rw-r--r--OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs (renamed from OpenSim/Tests/Clients/InstantMessage/IMClient.cs)31
-rw-r--r--OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs153
-rw-r--r--OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs81
-rw-r--r--OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs85
-rw-r--r--OpenSim/Tests/Robust/Server/DemonServer.cs69
-rw-r--r--OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/Configger/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs121
-rw-r--r--OpenSim/Tools/pCampBot/BotManager.cs3
-rw-r--r--OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs2
125 files changed, 5364 insertions, 1777 deletions
diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs
index 5ad087a..0a7fb5f 100644
--- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs
+++ b/OpenSim/Addons/Groups/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.Groups", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.Groups", 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/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs
index 3868912..3e993b4 100644
--- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs
+++ b/OpenSim/Addons/OfflineIM/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.OfflineIM", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.OfflineIM", 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/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
index 0ed47a3..6c3c3e3 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
@@ -63,7 +63,7 @@ using Mono.Addins;
63// by using the '*' as shown below: 63// by using the '*' as shown below:
64// [assembly: AssemblyVersion("0.7.6.*")] 64// [assembly: AssemblyVersion("0.7.6.*")]
65 65
66[assembly : AssemblyVersion("0.8.1.*")] 66[assembly : AssemblyVersion("0.8.2.*")]
67 67
68[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)] 68[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)]
69[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] 69[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
index d14938f..021209f 100644
--- a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/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.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] 36[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
index ffeff3a..443e323 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/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.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)] 36[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
new file mode 100644
index 0000000..810096f
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
@@ -0,0 +1,840 @@
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;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Framework.Capabilities;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42
43namespace OpenSim.Capabilities.Handlers
44{
45 public class FetchInvDescHandler
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private IInventoryService m_InventoryService;
51 private ILibraryService m_LibraryService;
52// private object m_fetchLock = new Object();
53
54 public FetchInvDescHandler(IInventoryService invService, ILibraryService libService)
55 {
56 m_InventoryService = invService;
57 m_LibraryService = libService;
58 }
59
60
61 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
62 {
63
64 // nasty temporary hack here, the linden client falsely
65 // identifies the uuid 00000000-0000-0000-0000-000000000000
66 // as a string which breaks us
67 //
68 // correctly mark it as a uuid
69 //
70 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
71
72 // another hack <integer>1</integer> results in a
73 // System.ArgumentException: Object type System.Int32 cannot
74 // be converted to target type: System.Boolean
75 //
76 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
77 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
78
79 Hashtable hash = new Hashtable();
80 try
81 {
82 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
83 }
84 catch (LLSD.LLSDParseException e)
85 {
86 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
87 m_log.Error("Request: " + request);
88 }
89
90 ArrayList foldersrequested = (ArrayList)hash["folders"];
91
92 string response = "";
93 string bad_folders_response = "";
94
95 List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
96 for (int i = 0; i < foldersrequested.Count; i++)
97 {
98 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
99
100 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
101
102 try
103 {
104 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
105 }
106 catch (Exception e)
107 {
108 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
109 continue;
110 }
111
112 // Filter duplicate folder ids that bad viewers may send
113 if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null)
114 folders.Add(llsdRequest);
115 }
116
117 if (folders.Count > 0)
118 {
119 List<UUID> bad_folders = new List<UUID>();
120 List<InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);
121 //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
122
123 if (invcollSet == null)
124 {
125 m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
126 return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse);
127 }
128
129 string inventoryitemstr = string.Empty;
130 foreach (InventoryCollectionWithDescendents icoll in invcollSet)
131 {
132 LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);
133
134 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
135 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
136 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
137
138 response += inventoryitemstr;
139 }
140
141 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
142 foreach (UUID bad in bad_folders)
143 bad_folders_response += "<uuid>" + bad + "</uuid>";
144 }
145
146 if (response.Length == 0)
147 {
148 /* Viewers expect a bad_folders array when not available */
149 if (bad_folders_response.Length != 0)
150 {
151 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
152 }
153 else
154 {
155 response = "<llsd><map><key>folders</key><array /></map></llsd>";
156 }
157 }
158 else
159 {
160 if (bad_folders_response.Length != 0)
161 {
162 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
163 }
164 else
165 {
166 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
167 }
168 }
169
170 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count);
171 //m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);
172
173 return response;
174
175 }
176
177 /// <summary>
178 /// Construct an LLSD reply packet to a CAPS inventory request
179 /// </summary>
180 /// <param name="invFetch"></param>
181 /// <returns></returns>
182 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
183 {
184 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
185 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
186 contents.agent_id = invFetch.owner_id;
187 contents.owner_id = invFetch.owner_id;
188 contents.folder_id = invFetch.folder_id;
189
190 reply.folders.Array.Add(contents);
191 InventoryCollection inv = new InventoryCollection();
192 inv.Folders = new List<InventoryFolderBase>();
193 inv.Items = new List<InventoryItemBase>();
194 int version = 0;
195 int descendents = 0;
196
197 inv
198 = Fetch(
199 invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
200 invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
201
202 if (inv != null && inv.Folders != null)
203 {
204 foreach (InventoryFolderBase invFolder in inv.Folders)
205 {
206 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
207 }
208
209 descendents += inv.Folders.Count;
210 }
211
212 if (inv != null && inv.Items != null)
213 {
214 foreach (InventoryItemBase invItem in inv.Items)
215 {
216 contents.items.Array.Add(ConvertInventoryItem(invItem));
217 }
218 }
219
220 contents.descendents = descendents;
221 contents.version = version;
222
223 //m_log.DebugFormat(
224 // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
225 // invFetch.folder_id,
226 // invFetch.fetch_items,
227 // invFetch.fetch_folders,
228 // contents.items.Array.Count,
229 // contents.categories.Array.Count,
230 // invFetch.owner_id);
231
232 return reply;
233 }
234
235 private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents)
236 {
237 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
238 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
239 contents.agent_id = inv.OwnerID;
240 contents.owner_id = inv.OwnerID;
241 contents.folder_id = inv.FolderID;
242
243 reply.folders.Array.Add(contents);
244
245 if (inv.Folders != null)
246 {
247 foreach (InventoryFolderBase invFolder in inv.Folders)
248 {
249 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
250 }
251
252 descendents += inv.Folders.Count;
253 }
254
255 if (inv.Items != null)
256 {
257 foreach (InventoryItemBase invItem in inv.Items)
258 {
259 contents.items.Array.Add(ConvertInventoryItem(invItem));
260 }
261 }
262
263 contents.descendents = descendents;
264 contents.version = inv.Version;
265
266 return reply;
267 }
268 /// <summary>
269 /// Old style. Soon to be deprecated.
270 /// </summary>
271 /// <param name="request"></param>
272 /// <param name="httpRequest"></param>
273 /// <param name="httpResponse"></param>
274 /// <returns></returns>
275 [Obsolete]
276 private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
277 {
278 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
279
280 string response = "";
281 string bad_folders_response = "";
282
283 for (int i = 0; i < foldersrequested.Count; i++)
284 {
285 string inventoryitemstr = "";
286 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
287
288 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
289
290 try
291 {
292 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
293 }
294 catch (Exception e)
295 {
296 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
297 }
298
299 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
300
301 if (null == reply)
302 {
303 bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
304 }
305 else
306 {
307 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
308 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
309 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
310 }
311
312 response += inventoryitemstr;
313 }
314
315 if (response.Length == 0)
316 {
317 /* Viewers expect a bad_folders array when not available */
318 if (bad_folders_response.Length != 0)
319 {
320 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
321 }
322 else
323 {
324 response = "<llsd><map><key>folders</key><array /></map></llsd>";
325 }
326 }
327 else
328 {
329 if (bad_folders_response.Length != 0)
330 {
331 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
332 }
333 else
334 {
335 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
336 }
337 }
338
339 // m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
340 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
341
342 return response;
343
344 // }
345 }
346
347 /// <summary>
348 /// Handle the caps inventory descendents fetch.
349 /// </summary>
350 /// <param name="agentID"></param>
351 /// <param name="folderID"></param>
352 /// <param name="ownerID"></param>
353 /// <param name="fetchFolders"></param>
354 /// <param name="fetchItems"></param>
355 /// <param name="sortOrder"></param>
356 /// <param name="version"></param>
357 /// <returns>An empty InventoryCollection if the inventory look up failed</returns>
358 [Obsolete]
359 private InventoryCollection Fetch(
360 UUID agentID, UUID folderID, UUID ownerID,
361 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
362 {
363 //m_log.DebugFormat(
364 // "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
365 // fetchFolders, fetchItems, folderID, agentID);
366
367 // FIXME MAYBE: We're not handling sortOrder!
368
369 version = 0;
370 descendents = 0;
371
372 InventoryFolderImpl fold;
373 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
374 {
375 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
376 {
377 InventoryCollection ret = new InventoryCollection();
378 ret.Folders = new List<InventoryFolderBase>();
379 ret.Items = fold.RequestListOfItems();
380 descendents = ret.Folders.Count + ret.Items.Count;
381
382 return ret;
383 }
384 }
385
386 InventoryCollection contents = new InventoryCollection();
387
388 if (folderID != UUID.Zero)
389 {
390 InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
391
392 if (fetchedContents == null)
393 {
394 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
395 return contents;
396 }
397 contents = fetchedContents;
398 InventoryFolderBase containingFolder = new InventoryFolderBase();
399 containingFolder.ID = folderID;
400 containingFolder.Owner = agentID;
401 containingFolder = m_InventoryService.GetFolder(containingFolder);
402
403 if (containingFolder != null)
404 {
405 //m_log.DebugFormat(
406 // "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
407 // containingFolder.Name, containingFolder.ID, agentID);
408
409 version = containingFolder.Version;
410
411 if (fetchItems)
412 {
413 List<InventoryItemBase> itemsToReturn = contents.Items;
414 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
415
416 // descendents must only include the links, not the linked items we add
417 descendents = originalItems.Count;
418
419 // Add target items for links in this folder before the links themselves.
420 foreach (InventoryItemBase item in originalItems)
421 {
422 if (item.AssetType == (int)AssetType.Link)
423 {
424 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
425
426 // Take care of genuinely broken links where the target doesn't exist
427 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
428 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
429 // rather than having to keep track of every folder requested in the recursion.
430 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
431 itemsToReturn.Insert(0, linkedItem);
432 }
433 }
434
435 // Now scan for folder links and insert the items they target and those links at the head of the return data
436 foreach (InventoryItemBase item in originalItems)
437 {
438 if (item.AssetType == (int)AssetType.LinkFolder)
439 {
440 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
441 List<InventoryItemBase> links = linkedFolderContents.Items;
442
443 itemsToReturn.InsertRange(0, links);
444
445 foreach (InventoryItemBase link in linkedFolderContents.Items)
446 {
447 // Take care of genuinely broken links where the target doesn't exist
448 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
449 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
450 // rather than having to keep track of every folder requested in the recursion.
451 if (link != null)
452 {
453// m_log.DebugFormat(
454// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
455// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
456
457 InventoryItemBase linkedItem
458 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
459
460 if (linkedItem != null)
461 itemsToReturn.Insert(0, linkedItem);
462 }
463 }
464 }
465 }
466 }
467
468// foreach (InventoryItemBase item in contents.Items)
469// {
470// m_log.DebugFormat(
471// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
472// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
473// }
474
475 // =====
476
477//
478// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
479// {
480// m_log.DebugFormat(
481// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
482// linkedItem.Name, folderID, agentID);
483//
484// contents.Items.Add(linkedItem);
485// }
486//
487// // If the folder requested contains links, then we need to send those folders first, otherwise the links
488// // will be broken in the viewer.
489// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
490// foreach (InventoryItemBase item in contents.Items)
491// {
492// if (item.AssetType == (int)AssetType.Link)
493// {
494// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
495//
496// // Take care of genuinely broken links where the target doesn't exist
497// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
498// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
499// // rather than having to keep track of every folder requested in the recursion.
500// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
501// {
502// // We don't need to send the folder if source and destination of the link are in the same
503// // folder.
504// if (linkedItem.Folder != containingFolder.ID)
505// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
506// }
507// }
508// }
509//
510// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
511// {
512// m_log.DebugFormat(
513// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
514// linkedItemFolderId, folderID, agentID);
515//
516// int dummyVersion;
517// InventoryCollection linkedCollection
518// = Fetch(
519// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
520//
521// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
522// linkedFolder.Owner = agentID;
523// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
524//
525//// contents.Folders.AddRange(linkedCollection.Folders);
526//
527// contents.Folders.Add(linkedFolder);
528// contents.Items.AddRange(linkedCollection.Items);
529// }
530// }
531 }
532 }
533 else
534 {
535 // Lost items don't really need a version
536 version = 1;
537 }
538
539 return contents;
540
541 }
542
543 private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result)
544 {
545 InventoryFolderImpl fold;
546 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
547 {
548 List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner);
549 fetchFolders.RemoveAll(f => libfolders.Contains(f));
550
551 //m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count);
552
553 foreach (LLSDFetchInventoryDescendents f in libfolders)
554 {
555 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
556 {
557 InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
558 ret.Collection = new InventoryCollection();
559 ret.Collection.Folders = new List<InventoryFolderBase>();
560 ret.Collection.Items = fold.RequestListOfItems();
561 ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
562 ret.Collection.FolderID = f.folder_id;
563 ret.Collection.Version = fold.Version;
564
565 ret.Descendents = ret.Collection.Items.Count;
566 result.Add(ret);
567
568 //m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
569 }
570 }
571 }
572 }
573
574 private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders)
575 {
576 //m_log.DebugFormat(
577 // "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id);
578
579 // FIXME MAYBE: We're not handling sortOrder!
580
581 List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
582
583 AddLibraryFolders(fetchFolders, result);
584
585 if (fetchFolders.Count > 0)
586 {
587 UUID[] fids = new UUID[fetchFolders.Count];
588 int i = 0;
589 foreach (LLSDFetchInventoryDescendents f in fetchFolders)
590 fids[i++] = f.folder_id;
591
592 //m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids));
593
594 InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids);
595
596 if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0))
597 {
598 //m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id);
599 return null;
600 }
601
602 i = 0;
603 // Do some post-processing. May need to fetch more from inv server for links
604 foreach (InventoryCollection contents in fetchedContents)
605 {
606 // Find the original request
607 LLSDFetchInventoryDescendents freq = fetchFolders[i++];
608
609 InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
610 coll.Collection = contents;
611
612 if (BadFolder(freq, contents, bad_folders))
613 continue;
614
615 // Next: link management
616 ProcessLinks(freq, coll);
617
618 result.Add(coll);
619 }
620 }
621
622 return result;
623 }
624
625 private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders)
626 {
627 bool bad = false;
628 if (contents == null)
629 {
630 bad_folders.Add(freq.folder_id);
631 bad = true;
632 }
633
634 // The inventory server isn't sending FolderID in the collection...
635 // Must fetch it individually
636 if (contents.FolderID == UUID.Zero)
637 {
638 InventoryFolderBase containingFolder = new InventoryFolderBase();
639 containingFolder.ID = freq.folder_id;
640 containingFolder.Owner = freq.owner_id;
641 containingFolder = m_InventoryService.GetFolder(containingFolder);
642
643 if (containingFolder != null)
644 {
645 contents.FolderID = containingFolder.ID;
646 contents.OwnerID = containingFolder.Owner;
647 contents.Version = containingFolder.Version;
648 }
649 else
650 {
651 // Was it really a request for folder Zero?
652 // This is an overkill, but Firestorm really asks for folder Zero.
653 // I'm leaving the code here for the time being, but commented.
654 if (freq.folder_id == UUID.Zero)
655 {
656 //coll.Collection.OwnerID = freq.owner_id;
657 //coll.Collection.FolderID = contents.FolderID;
658 //containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
659 //if (containingFolder != null)
660 //{
661 // m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
662 // coll.Collection.Folders.Clear();
663 // coll.Collection.Folders.Add(containingFolder);
664 // if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
665 // {
666 // InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
667 // lib.Name = m_LibraryService.LibraryRootFolder.Name;
668 // lib.Type = m_LibraryService.LibraryRootFolder.Type;
669 // lib.Version = m_LibraryService.LibraryRootFolder.Version;
670 // coll.Collection.Folders.Add(lib);
671 // }
672 // coll.Collection.Items.Clear();
673 //}
674 }
675 else
676 {
677 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
678 bad_folders.Add(freq.folder_id);
679 }
680 bad = true;
681 }
682 }
683
684 return bad;
685 }
686
687 private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll)
688 {
689 InventoryCollection contents = coll.Collection;
690
691 if (freq.fetch_items && contents.Items != null)
692 {
693 List<InventoryItemBase> itemsToReturn = contents.Items;
694
695 // descendents must only include the links, not the linked items we add
696 coll.Descendents = itemsToReturn.Count;
697
698 // Add target items for links in this folder before the links themselves.
699 List<UUID> itemIDs = new List<UUID>();
700 List<UUID> folderIDs = new List<UUID>();
701 foreach (InventoryItemBase item in itemsToReturn)
702 {
703 //m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
704 if (item.AssetType == (int)AssetType.Link)
705 itemIDs.Add(item.AssetID);
706
707 else if (item.AssetType == (int)AssetType.LinkFolder)
708 folderIDs.Add(item.AssetID);
709 }
710
711 //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
712
713 // Scan for folder links and insert the items they target and those links at the head of the return data
714 if (folderIDs.Count > 0)
715 {
716 InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray());
717 foreach (InventoryCollection linkedFolderContents in linkedFolders)
718 {
719 List<InventoryItemBase> links = linkedFolderContents.Items;
720
721 itemsToReturn.InsertRange(0, links);
722
723 foreach (InventoryItemBase link in linkedFolderContents.Items)
724 {
725 // Take care of genuinely broken links where the target doesn't exist
726 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
727 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
728 // rather than having to keep track of every folder requested in the recursion.
729 if (link != null)
730 {
731 //m_log.DebugFormat(
732 // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})",
733 // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID);
734 itemIDs.Add(link.ID);
735 }
736 }
737 }
738 }
739
740 if (itemIDs.Count > 0)
741 {
742 InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
743 if (linked == null)
744 {
745 // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
746 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
747 linked = new InventoryItemBase[itemIDs.Count];
748 int i = 0;
749 InventoryItemBase item = new InventoryItemBase();
750 item.Owner = freq.owner_id;
751 foreach (UUID id in itemIDs)
752 {
753 item.ID = id;
754 linked[i++] = m_InventoryService.GetItem(item);
755 }
756 }
757
758 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id);
759 //foreach (InventoryItemBase item in itemsToReturn)
760 // m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder);
761
762 if (linked != null)
763 {
764 foreach (InventoryItemBase linkedItem in linked)
765 {
766 // Take care of genuinely broken links where the target doesn't exist
767 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
768 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
769 // rather than having to keep track of every folder requested in the recursion.
770 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
771 {
772 itemsToReturn.Insert(0, linkedItem);
773 //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
774 }
775 }
776 }
777 }
778 }
779
780 }
781
782 /// <summary>
783 /// Convert an internal inventory folder object into an LLSD object.
784 /// </summary>
785 /// <param name="invFolder"></param>
786 /// <returns></returns>
787 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
788 {
789 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
790 llsdFolder.folder_id = invFolder.ID;
791 llsdFolder.parent_id = invFolder.ParentID;
792 llsdFolder.name = invFolder.Name;
793 llsdFolder.type = invFolder.Type;
794 llsdFolder.preferred_type = -1;
795
796 return llsdFolder;
797 }
798
799 /// <summary>
800 /// Convert an internal inventory item object into an LLSD object.
801 /// </summary>
802 /// <param name="invItem"></param>
803 /// <returns></returns>
804 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
805 {
806 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
807 llsdItem.asset_id = invItem.AssetID;
808 llsdItem.created_at = invItem.CreationDate;
809 llsdItem.desc = invItem.Description;
810 llsdItem.flags = (int)invItem.Flags;
811 llsdItem.item_id = invItem.ID;
812 llsdItem.name = invItem.Name;
813 llsdItem.parent_id = invItem.Folder;
814 llsdItem.type = invItem.AssetType;
815 llsdItem.inv_type = invItem.InvType;
816
817 llsdItem.permissions = new LLSDPermissions();
818 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
819 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
820 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
821 llsdItem.permissions.group_id = invItem.GroupID;
822 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
823 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
824 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
825 llsdItem.permissions.owner_id = invItem.Owner;
826 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
827 llsdItem.sale_info = new LLSDSaleInfo();
828 llsdItem.sale_info.sale_price = invItem.SalePrice;
829 llsdItem.sale_info.sale_type = invItem.SaleType;
830
831 return llsdItem;
832 }
833 }
834
835 class InventoryCollectionWithDescendents
836 {
837 public InventoryCollection Collection;
838 public int Descendents;
839 }
840} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs
index 6fbe173..6fbe173 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
index b67b326..b67b326 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
new file mode 100644
index 0000000..d34423d
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs
@@ -0,0 +1,228 @@
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.Linq;
31using System.Net;
32using log4net;
33using log4net.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenSim.Capabilities.Handlers;
37using OpenSim.Framework;
38using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42
43namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
44{
45 [TestFixture]
46 public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase
47 {
48 private UUID m_userID = UUID.Zero;
49 private Scene m_scene;
50 private UUID m_rootFolderID;
51 private int m_rootDescendents;
52 private UUID m_notecardsFolder;
53 private UUID m_objectsFolder;
54
55 private void Init()
56 {
57 // Create an inventory that looks like this:
58 //
59 // /My Inventory
60 // <other system folders>
61 // /Objects
62 // Some Object
63 // /Notecards
64 // Notecard 1
65 // Notecard 2
66 // /Test Folder
67 // Link to notecard -> /Notecards/Notecard 2
68 // Link to Objects folder -> /Objects
69
70 m_scene = new SceneHelpers().SetupScene();
71
72 m_scene.InventoryService.CreateUserInventory(m_userID);
73
74 m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
75
76 InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Object);
77 m_objectsFolder = of.ID;
78
79 // Add an object
80 InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID);
81 item.AssetID = UUID.Random();
82 item.AssetType = (int)AssetType.Object;
83 item.Folder = m_objectsFolder;
84 item.Name = "Some Object";
85 m_scene.InventoryService.AddItem(item);
86
87 InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Notecard);
88 m_notecardsFolder = ncf.ID;
89
90 // Add a notecard
91 item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID);
92 item.AssetID = UUID.Random();
93 item.AssetType = (int)AssetType.Notecard;
94 item.Folder = m_notecardsFolder;
95 item.Name = "Test Notecard 1";
96 m_scene.InventoryService.AddItem(item);
97 // Add another notecard
98 item.ID = new UUID("20000000-0000-0000-0000-000000000002");
99 item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a");
100 item.Name = "Test Notecard 2";
101 m_scene.InventoryService.AddItem(item);
102
103 // Add a folder
104 InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID);
105 m_scene.InventoryService.AddFolder(folder);
106
107 // Add a link to notecard 2 in Test Folder
108 item.AssetID = item.ID; // use item ID of notecard 2
109 item.ID = new UUID("40000000-0000-0000-0000-000000000004");
110 item.AssetType = (int)AssetType.Link;
111 item.Folder = folder.ID;
112 item.Name = "Link to notecard";
113 m_scene.InventoryService.AddItem(item);
114
115 // Add a link to the Objects folder in Test Folder
116 item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Object).ID; // use item ID of Objects folder
117 item.ID = new UUID("50000000-0000-0000-0000-000000000005");
118 item.AssetType = (int)AssetType.LinkFolder;
119 item.Folder = folder.ID;
120 item.Name = "Link to Objects folder";
121 m_scene.InventoryService.AddItem(item);
122
123 InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID);
124 m_rootDescendents = coll.Items.Count + coll.Folders.Count;
125 Console.WriteLine("Number of descendents: " + m_rootDescendents);
126 }
127
128 [Test]
129 public void Test_001_SimpleFolder()
130 {
131 TestHelpers.InMethod();
132
133 Init();
134
135 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null);
136 TestOSHttpRequest req = new TestOSHttpRequest();
137 TestOSHttpResponse resp = new TestOSHttpResponse();
138
139 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
140 request += m_rootFolderID;
141 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
142
143 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
144
145 Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
146 Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
147 Assert.That(llsdresponse.Contains("00000000-0000-0000-0000-000000000000"), Is.True, "Response should contain userID");
148
149 string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
150 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents");
151 Console.WriteLine(llsdresponse);
152 }
153
154 [Test]
155 public void Test_002_MultipleFolders()
156 {
157 TestHelpers.InMethod();
158
159 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null);
160 TestOSHttpRequest req = new TestOSHttpRequest();
161 TestOSHttpResponse resp = new TestOSHttpResponse();
162
163 string request = "<llsd><map><key>folders</key><array>";
164 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
165 request += m_rootFolderID;
166 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
167 request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
168 request += m_notecardsFolder;
169 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
170 request += "</array></map></llsd>";
171
172 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
173 Console.WriteLine(llsdresponse);
174
175 string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
176 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder");
177 descendents = "descendents</key><integer>2</integer>";
178 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder");
179
180 Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response");
181 Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response");
182 }
183
184 [Test]
185 public void Test_003_Links()
186 {
187 TestHelpers.InMethod();
188
189 FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null);
190 TestOSHttpRequest req = new TestOSHttpRequest();
191 TestOSHttpResponse resp = new TestOSHttpResponse();
192
193 string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
194 request += "f0000000-0000-0000-0000-00000000000f";
195 request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
196
197 string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
198 Console.WriteLine(llsdresponse);
199
200 string descendents = "descendents</key><integer>2</integer>";
201 Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder");
202
203 // Make sure that the note card link is included
204 Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing");
205
206 //Make sure the notecard item itself is included
207 Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing");
208
209 // Make sure that the source item is before the link item
210 int pos1 = llsdresponse.IndexOf("Test Notecard 2");
211 int pos2 = llsdresponse.IndexOf("Link to notecard");
212 Assert.Less(pos1, pos2, "Source of link is after link");
213
214 // Make sure the folder link is included
215 Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing");
216
217 // Make sure the objects inside the Objects folder are included
218 // Note: I'm not entirely sure this is needed, but that's what I found in the implementation
219 Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing");
220
221 // Make sure that the source item is before the link item
222 pos1 = llsdresponse.IndexOf("Some Object");
223 pos2 = llsdresponse.IndexOf("Link to Objects folder");
224 Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link");
225 }
226 }
227
228} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs
deleted file mode 100644
index 451575f..0000000
--- a/OpenSim/Capabilities/Handlers/FetchInventoryDescendents/FetchInvDescHandler.cs
+++ /dev/null
@@ -1,465 +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 System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Framework.Capabilities;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42
43namespace OpenSim.Capabilities.Handlers
44{
45 public class FetchInvDescHandler
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private IInventoryService m_InventoryService;
51 private ILibraryService m_LibraryService;
52// private object m_fetchLock = new Object();
53
54 public FetchInvDescHandler(IInventoryService invService, ILibraryService libService)
55 {
56 m_InventoryService = invService;
57 m_LibraryService = libService;
58 }
59
60 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 {
62// lock (m_fetchLock)
63// {
64// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request);
65
66 // nasty temporary hack here, the linden client falsely
67 // identifies the uuid 00000000-0000-0000-0000-000000000000
68 // as a string which breaks us
69 //
70 // correctly mark it as a uuid
71 //
72 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
73
74 // another hack <integer>1</integer> results in a
75 // System.ArgumentException: Object type System.Int32 cannot
76 // be converted to target type: System.Boolean
77 //
78 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
79 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
80
81 Hashtable hash = new Hashtable();
82 try
83 {
84 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
85 }
86 catch (LLSD.LLSDParseException e)
87 {
88 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
89 m_log.Error("Request: " + request);
90 }
91
92 ArrayList foldersrequested = (ArrayList)hash["folders"];
93
94 string response = "";
95 string bad_folders_response = "";
96
97 for (int i = 0; i < foldersrequested.Count; i++)
98 {
99 string inventoryitemstr = "";
100 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
101
102 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
103
104 try
105 {
106 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
107 }
108 catch (Exception e)
109 {
110 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
111 }
112 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
113
114 if (null == reply)
115 {
116 bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
117 }
118 else
119 {
120 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
121 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
122 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
123 }
124
125 response += inventoryitemstr;
126 }
127
128 if (response.Length == 0)
129 {
130 /* Viewers expect a bad_folders array when not available */
131 if (bad_folders_response.Length != 0)
132 {
133 response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
134 }
135 else
136 {
137 response = "<llsd><map><key>folders</key><array /></map></llsd>";
138 }
139 }
140 else
141 {
142 if (bad_folders_response.Length != 0)
143 {
144 response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
145 }
146 else
147 {
148 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
149 }
150 }
151
152// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
153 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
154
155 return response;
156
157// }
158 }
159
160 /// <summary>
161 /// Construct an LLSD reply packet to a CAPS inventory request
162 /// </summary>
163 /// <param name="invFetch"></param>
164 /// <returns></returns>
165 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
166 {
167 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
168 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
169 contents.agent_id = invFetch.owner_id;
170 contents.owner_id = invFetch.owner_id;
171 contents.folder_id = invFetch.folder_id;
172
173 reply.folders.Array.Add(contents);
174 InventoryCollection inv = new InventoryCollection();
175 inv.Folders = new List<InventoryFolderBase>();
176 inv.Items = new List<InventoryItemBase>();
177 int version = 0;
178 int descendents = 0;
179
180 inv
181 = Fetch(
182 invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
183 invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
184
185 if (inv != null && inv.Folders != null)
186 {
187 foreach (InventoryFolderBase invFolder in inv.Folders)
188 {
189 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
190 }
191
192 descendents += inv.Folders.Count;
193 }
194
195 if (inv != null && inv.Items != null)
196 {
197 foreach (InventoryItemBase invItem in inv.Items)
198 {
199 contents.items.Array.Add(ConvertInventoryItem(invItem));
200 }
201 }
202
203 contents.descendents = descendents;
204 contents.version = version;
205
206// m_log.DebugFormat(
207// "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
208// invFetch.folder_id,
209// invFetch.fetch_items,
210// invFetch.fetch_folders,
211// contents.items.Array.Count,
212// contents.categories.Array.Count,
213// invFetch.owner_id);
214
215 return reply;
216 }
217
218 /// <summary>
219 /// Handle the caps inventory descendents fetch.
220 /// </summary>
221 /// <param name="agentID"></param>
222 /// <param name="folderID"></param>
223 /// <param name="ownerID"></param>
224 /// <param name="fetchFolders"></param>
225 /// <param name="fetchItems"></param>
226 /// <param name="sortOrder"></param>
227 /// <param name="version"></param>
228 /// <returns>An empty InventoryCollection if the inventory look up failed</returns>
229 private InventoryCollection Fetch(
230 UUID agentID, UUID folderID, UUID ownerID,
231 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
232 {
233 //m_log.DebugFormat(
234 // "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
235 // fetchFolders, fetchItems, folderID, agentID);
236
237 // FIXME MAYBE: We're not handling sortOrder!
238
239 version = 0;
240 descendents = 0;
241
242 InventoryFolderImpl fold;
243 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
244 {
245 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
246 {
247 InventoryCollection ret = new InventoryCollection();
248 ret.Folders = new List<InventoryFolderBase>();
249 ret.Items = fold.RequestListOfItems();
250 descendents = ret.Folders.Count + ret.Items.Count;
251
252 return ret;
253 }
254 }
255
256 InventoryCollection contents = new InventoryCollection();
257
258 if (folderID != UUID.Zero)
259 {
260 InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
261
262 if (fetchedContents == null)
263 {
264 m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
265 return contents;
266 }
267
268 contents = fetchedContents;
269 InventoryFolderBase containingFolder = new InventoryFolderBase();
270 containingFolder.ID = folderID;
271 containingFolder.Owner = agentID;
272 containingFolder = m_InventoryService.GetFolder(containingFolder);
273
274 if (containingFolder != null)
275 {
276// m_log.DebugFormat(
277// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
278// containingFolder.Name, containingFolder.ID, agentID);
279
280 version = containingFolder.Version;
281
282 if (fetchItems)
283 {
284 List<InventoryItemBase> itemsToReturn = contents.Items;
285 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
286
287 // descendents must only include the links, not the linked items we add
288 descendents = originalItems.Count;
289
290 // Add target items for links in this folder before the links themselves.
291 foreach (InventoryItemBase item in originalItems)
292 {
293 if (item.AssetType == (int)AssetType.Link)
294 {
295 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
296
297 // Take care of genuinely broken links where the target doesn't exist
298 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
299 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
300 // rather than having to keep track of every folder requested in the recursion.
301 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
302 itemsToReturn.Insert(0, linkedItem);
303 }
304 }
305
306 // Now scan for folder links and insert the items they target and those links at the head of the return data
307 foreach (InventoryItemBase item in originalItems)
308 {
309 if (item.AssetType == (int)AssetType.LinkFolder)
310 {
311 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
312 List<InventoryItemBase> links = linkedFolderContents.Items;
313
314 itemsToReturn.InsertRange(0, links);
315
316 foreach (InventoryItemBase link in linkedFolderContents.Items)
317 {
318 // Take care of genuinely broken links where the target doesn't exist
319 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
320 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
321 // rather than having to keep track of every folder requested in the recursion.
322 if (link != null)
323 {
324// m_log.DebugFormat(
325// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
326// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
327
328 InventoryItemBase linkedItem
329 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
330
331 if (linkedItem != null)
332 itemsToReturn.Insert(0, linkedItem);
333 }
334 }
335 }
336 }
337 }
338
339// foreach (InventoryItemBase item in contents.Items)
340// {
341// m_log.DebugFormat(
342// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
343// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
344// }
345
346 // =====
347
348//
349// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
350// {
351// m_log.DebugFormat(
352// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
353// linkedItem.Name, folderID, agentID);
354//
355// contents.Items.Add(linkedItem);
356// }
357//
358// // If the folder requested contains links, then we need to send those folders first, otherwise the links
359// // will be broken in the viewer.
360// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
361// foreach (InventoryItemBase item in contents.Items)
362// {
363// if (item.AssetType == (int)AssetType.Link)
364// {
365// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
366//
367// // Take care of genuinely broken links where the target doesn't exist
368// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
369// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
370// // rather than having to keep track of every folder requested in the recursion.
371// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
372// {
373// // We don't need to send the folder if source and destination of the link are in the same
374// // folder.
375// if (linkedItem.Folder != containingFolder.ID)
376// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
377// }
378// }
379// }
380//
381// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
382// {
383// m_log.DebugFormat(
384// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
385// linkedItemFolderId, folderID, agentID);
386//
387// int dummyVersion;
388// InventoryCollection linkedCollection
389// = Fetch(
390// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
391//
392// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
393// linkedFolder.Owner = agentID;
394// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
395//
396//// contents.Folders.AddRange(linkedCollection.Folders);
397//
398// contents.Folders.Add(linkedFolder);
399// contents.Items.AddRange(linkedCollection.Items);
400// }
401// }
402 }
403 }
404 else
405 {
406 // Lost items don't really need a version
407 version = 1;
408 }
409
410 return contents;
411
412 }
413 /// <summary>
414 /// Convert an internal inventory folder object into an LLSD object.
415 /// </summary>
416 /// <param name="invFolder"></param>
417 /// <returns></returns>
418 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
419 {
420 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
421 llsdFolder.folder_id = invFolder.ID;
422 llsdFolder.parent_id = invFolder.ParentID;
423 llsdFolder.name = invFolder.Name;
424 llsdFolder.type = invFolder.Type;
425 llsdFolder.preferred_type = -1;
426
427 return llsdFolder;
428 }
429
430 /// <summary>
431 /// Convert an internal inventory item object into an LLSD object.
432 /// </summary>
433 /// <param name="invItem"></param>
434 /// <returns></returns>
435 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
436 {
437 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
438 llsdItem.asset_id = invItem.AssetID;
439 llsdItem.created_at = invItem.CreationDate;
440 llsdItem.desc = invItem.Description;
441 llsdItem.flags = (int)invItem.Flags;
442 llsdItem.item_id = invItem.ID;
443 llsdItem.name = invItem.Name;
444 llsdItem.parent_id = invItem.Folder;
445 llsdItem.type = invItem.AssetType;
446 llsdItem.inv_type = invItem.InvType;
447
448 llsdItem.permissions = new LLSDPermissions();
449 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
450 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
451 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
452 llsdItem.permissions.group_id = invItem.GroupID;
453 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
454 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
455 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
456 llsdItem.permissions.owner_id = invItem.Owner;
457 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
458 llsdItem.sale_info = new LLSDSaleInfo();
459 llsdItem.sale_info.sale_price = invItem.SalePrice;
460 llsdItem.sale_info.sale_type = invItem.SaleType;
461
462 return llsdItem;
463 }
464 }
465} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
index 296cb03..3579649 100644
--- a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Handlers/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/Data/MySQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
index 249842c..b46d175 100644
--- a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.8.1.*")] 64[assembly : AssemblyVersion("0.8.2.*")]
65 65
diff --git a/OpenSim/Data/Null/Properties/AssemblyInfo.cs b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
index 13e28a8..a827bd0 100644
--- a/OpenSim/Data/Null/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.8.1.*")] 64[assembly : AssemblyVersion("0.8.2.*")]
65 65
diff --git a/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
index 1c65dbe..1e88b2c 100644
--- a/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.8.1.*")] 64[assembly : AssemblyVersion("0.8.2.*")]
65 65
diff --git a/OpenSim/Data/Properties/AssemblyInfo.cs b/OpenSim/Data/Properties/AssemblyInfo.cs
index 4e41308..b1f234b 100644
--- a/OpenSim/Data/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.8.1.*")] 64[assembly : AssemblyVersion("0.8.2.*")]
65 65
diff --git a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
index 2befd13..d2e62d2 100644
--- a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.8.1.*")] 64[assembly : AssemblyVersion("0.8.2.*")]
65 65
diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs
index 5a15568..a797424 100644
--- a/OpenSim/Framework/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssemblyInfo.cs
@@ -59,4 +59,4 @@ using System.Runtime.InteropServices;
59// Revision 59// Revision
60// 60//
61 61
62[assembly : AssemblyVersion("0.8.1.*")] 62[assembly : AssemblyVersion("0.8.2.*")]
diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
index 26d0351..cd182d6 100644
--- a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssetLoader/Filesystem/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/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
index 907cebd..b398167 100644
--- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.8.1.*")] 64[assembly : AssemblyVersion("0.8.2.*")]
65 65
diff --git a/OpenSim/Framework/Console/AssemblyInfo.cs b/OpenSim/Framework/Console/AssemblyInfo.cs
index 4e50e44..67af471 100644
--- a/OpenSim/Framework/Console/AssemblyInfo.cs
+++ b/OpenSim/Framework/Console/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/Framework/InventoryCollection.cs b/OpenSim/Framework/InventoryCollection.cs
index 7049902..59655eb 100644
--- a/OpenSim/Framework/InventoryCollection.cs
+++ b/OpenSim/Framework/InventoryCollection.cs
@@ -37,6 +37,8 @@ namespace OpenSim.Framework
37 { 37 {
38 public List<InventoryFolderBase> Folders; 38 public List<InventoryFolderBase> Folders;
39 public List<InventoryItemBase> Items; 39 public List<InventoryItemBase> Items;
40 public UUID UserID; 40 public UUID OwnerID;
41 public UUID FolderID;
42 public int Version;
41 } 43 }
42} 44}
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
index ee82753..b08e4f7 100644
--- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Monitoring/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/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
index 4341560..3bcbe2f 100644
--- a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Filesystem/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/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
index e7efdf4..1b2519c 100644
--- a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Web/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/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs
index 6debf65..64de18b 100644
--- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs
+++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs
@@ -125,7 +125,8 @@ namespace OpenSim.Framework.Serialization.External
125 /// <param name="userService">The service for retrieving user account information</param> 125 /// <param name="userService">The service for retrieving user account information</param>
126 /// <param name="scopeID">The scope of the user account information (Grid ID)</param> 126 /// <param name="scopeID">The scope of the user account information (Grid ID)</param>
127 /// <returns>The SceneObjectPart represented in XML2</returns> 127 /// <returns>The SceneObjectPart represented in XML2</returns>
128 public static string RewriteSOP(string xml, string homeURL, IUserAccountService userService, UUID scopeID) 128 [Obsolete("This method is deprecated. Use RewriteSOP instead.")]
129 public static string RewriteSOP_Old(string xml, string homeURL, IUserAccountService userService, UUID scopeID)
129 { 130 {
130 if (xml == string.Empty || homeURL == string.Empty || userService == null) 131 if (xml == string.Empty || homeURL == string.Empty || userService == null)
131 return xml; 132 return xml;
@@ -173,6 +174,187 @@ namespace OpenSim.Framework.Serialization.External
173 } 174 }
174 } 175 }
175 176
177 /// <summary>
178 /// Takes a XML representation of a SceneObjectPart and returns another XML representation
179 /// with creator data added to it.
180 /// </summary>
181 /// <param name="xml">The SceneObjectPart represented in XML2</param>
182 /// <param name="sceneName">An identifier for the component that's calling this function</param>
183 /// <param name="homeURL">The URL of the user agents service (home) for the creator</param>
184 /// <param name="userService">The service for retrieving user account information</param>
185 /// <param name="scopeID">The scope of the user account information (Grid ID)</param>
186 /// <returns>The SceneObjectPart represented in XML2</returns>
187 public static string RewriteSOP(string xmlData, string sceneName, string homeURL, IUserAccountService userService, UUID scopeID)
188 {
189 // Console.WriteLine("Input XML [{0}]", xmlData);
190 if (xmlData == string.Empty || homeURL == string.Empty || userService == null)
191 return xmlData;
192
193 using (StringWriter sw = new StringWriter())
194 using (XmlTextWriter writer = new XmlTextWriter(sw))
195 using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
196 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment }))
197 {
198 TransformXml(reader, writer, sceneName, homeURL, userService, scopeID);
199
200 // Console.WriteLine("Output: [{0}]", sw.ToString());
201
202 return sw.ToString();
203 }
204 }
205
206 protected static void TransformXml(XmlReader reader, XmlWriter writer, string sceneName, string homeURI, IUserAccountService userAccountService, UUID scopeID)
207 {
208 // m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML");
209
210 int sopDepth = -1;
211 UserAccount creator = null;
212 bool hasCreatorData = false;
213
214 while (reader.Read())
215 {
216 // Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name);
217
218 switch (reader.NodeType)
219 {
220 case XmlNodeType.Attribute:
221 // Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name);
222 writer.WriteAttributeString(reader.Name, reader.Value);
223 break;
224
225 case XmlNodeType.CDATA:
226 writer.WriteCData(reader.Value);
227 break;
228
229 case XmlNodeType.Comment:
230 writer.WriteComment(reader.Value);
231 break;
232
233 case XmlNodeType.DocumentType:
234 writer.WriteDocType(reader.Name, reader.Value, null, null);
235 break;
236
237 case XmlNodeType.Element:
238 // m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name);
239
240 writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
241
242 if (reader.HasAttributes)
243 {
244 while (reader.MoveToNextAttribute())
245 writer.WriteAttributeString(reader.Name, reader.Value);
246
247 reader.MoveToElement();
248 }
249
250 if (reader.LocalName == "SceneObjectPart")
251 {
252 if (sopDepth < 0)
253 {
254 sopDepth = reader.Depth;
255 // m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth);
256 }
257 }
258 else
259 {
260 if (sopDepth >= 0 && reader.Depth == sopDepth + 1)
261 {
262 if (reader.Name == "CreatorID")
263 {
264 reader.Read();
265 if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID")
266 {
267 reader.Read();
268
269 if (reader.NodeType == XmlNodeType.Text)
270 {
271 UUID uuid = UUID.Zero;
272 UUID.TryParse(reader.Value, out uuid);
273 creator = userAccountService.GetUserAccount(scopeID, uuid);
274 writer.WriteElementString("UUID", reader.Value);
275 reader.Read();
276 }
277 else
278 {
279 // If we unexpected run across mixed content in this node, still carry on
280 // transforming the subtree (this replicates earlier behaviour).
281 TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
282 }
283 }
284 else
285 {
286 // If we unexpected run across mixed content in this node, still carry on
287 // transforming the subtree (this replicates earlier behaviour).
288 TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
289 }
290 }
291 else if (reader.Name == "CreatorData")
292 {
293 reader.Read();
294 if (reader.NodeType == XmlNodeType.Text)
295 {
296 hasCreatorData = true;
297 writer.WriteString(reader.Value);
298 }
299 else
300 {
301 // If we unexpected run across mixed content in this node, still carry on
302 // transforming the subtree (this replicates earlier behaviour).
303 TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
304 }
305 }
306 }
307 }
308
309 if (reader.IsEmptyElement)
310 {
311 // m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name);
312 writer.WriteEndElement();
313 }
314
315 break;
316
317 case XmlNodeType.EndElement:
318 // m_log.DebugFormat("Depth {0} at EndElement", reader.Depth);
319 if (sopDepth == reader.Depth)
320 {
321 if (!hasCreatorData && creator != null)
322 writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", homeURI, creator.FirstName, creator.LastName));
323
324 // m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth");
325 sopDepth = -1;
326 creator = null;
327 hasCreatorData = false;
328 }
329 writer.WriteEndElement();
330 break;
331
332 case XmlNodeType.EntityReference:
333 writer.WriteEntityRef(reader.Name);
334 break;
335
336 case XmlNodeType.ProcessingInstruction:
337 writer.WriteProcessingInstruction(reader.Name, reader.Value);
338 break;
339
340 case XmlNodeType.Text:
341 writer.WriteString(reader.Value);
342 break;
343
344 case XmlNodeType.XmlDeclaration:
345 // For various reasons, not all serializations have xml declarations (or consistent ones)
346 // and as it's embedded inside a byte stream we don't need it anyway, so ignore.
347 break;
348
349 default:
350 m_log.WarnFormat(
351 "[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}",
352 reader.NodeType, sceneName);
353 break;
354 }
355 }
356 }
357
176 public static string CalcCreatorData(string homeURL, string name) 358 public static string CalcCreatorData(string homeURL, string name)
177 { 359 {
178 return homeURL + ";" + name; 360 return homeURL + ";" + name;
diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
index 11573d2..0cce722 100644
--- a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Serialization/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/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
index ddb7e59..63335bd 100644
--- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/HttpServer/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/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index c22c119..e403ba0 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -292,11 +292,11 @@ namespace OpenSim.Framework.Servers
292 + " 3 = full stack trace, including common threads\n", 292 + " 3 = full stack trace, including common threads\n",
293 HandleDebugThreadpoolLevel); 293 HandleDebugThreadpoolLevel);
294 294
295 m_console.Commands.AddCommand( 295// m_console.Commands.AddCommand(
296 "Debug", false, "show threadpool calls active", 296// "Debug", false, "show threadpool calls active",
297 "show threadpool calls active", 297// "show threadpool calls active",
298 "Show details about threadpool calls that are still active (currently waiting or in progress)", 298// "Show details about threadpool calls that are still active (currently waiting or in progress)",
299 HandleShowThreadpoolCallsActive); 299// HandleShowThreadpoolCallsActive);
300 300
301 m_console.Commands.AddCommand( 301 m_console.Commands.AddCommand(
302 "Debug", false, "show threadpool calls complete", 302 "Debug", false, "show threadpool calls complete",
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
diff --git a/OpenSim/Server/Base/Properties/AssemblyInfo.cs b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
index 0d583f0..e819a2b 100644
--- a/OpenSim/Server/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Base/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/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index d7d1306..1f2c54d 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -82,7 +82,9 @@ namespace OpenSim.Server.Base
82 argvConfig.AddSwitch("Startup", "logconfig", "g"); 82 argvConfig.AddSwitch("Startup", "logconfig", "g");
83 83
84 // Automagically create the ini file name 84 // Automagically create the ini file name
85 string fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); 85 string fileName = "";
86 if (Assembly.GetEntryAssembly() != null)
87 fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
86 string iniFile = fileName + ".ini"; 88 string iniFile = fileName + ".ini";
87 string logConfig = null; 89 string logConfig = null;
88 90
@@ -158,7 +160,11 @@ namespace OpenSim.Server.Base
158 MainConsole.Instance = new RemoteConsole(prompt); 160 MainConsole.Instance = new RemoteConsole(prompt);
159 ((RemoteConsole)MainConsole.Instance).ReadConfig(Config); 161 ((RemoteConsole)MainConsole.Instance).ReadConfig(Config);
160 } 162 }
161 else 163 else if (consoleType == "mock")
164 {
165 MainConsole.Instance = new MockConsole();
166 }
167 else if (consoleType == "local")
162 { 168 {
163 MainConsole.Instance = new LocalConsole(prompt, startupConfig); 169 MainConsole.Instance = new LocalConsole(prompt, startupConfig);
164 } 170 }
diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
index 0288fa6..cf0762b 100644
--- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
+++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
@@ -41,7 +41,9 @@ using OpenSim.Server.Handlers.Base;
41using log4net; 41using log4net;
42using OpenMetaverse; 42using OpenMetaverse;
43 43
44namespace OpenSim.Server.Handlers.Asset 44using System.Threading;
45
46namespace OpenSim.Server.Handlers.Inventory
45{ 47{
46 public class XInventoryInConnector : ServiceConnector 48 public class XInventoryInConnector : ServiceConnector
47 { 49 {
@@ -123,6 +125,8 @@ namespace OpenSim.Server.Handlers.Asset
123 return HandleGetFolderForType(request); 125 return HandleGetFolderForType(request);
124 case "GETFOLDERCONTENT": 126 case "GETFOLDERCONTENT":
125 return HandleGetFolderContent(request); 127 return HandleGetFolderContent(request);
128 case "GETMULTIPLEFOLDERSCONTENT":
129 return HandleGetMultipleFoldersContent(request);
126 case "GETFOLDERITEMS": 130 case "GETFOLDERITEMS":
127 return HandleGetFolderItems(request); 131 return HandleGetFolderItems(request);
128 case "ADDFOLDER": 132 case "ADDFOLDER":
@@ -145,6 +149,8 @@ namespace OpenSim.Server.Handlers.Asset
145 return HandleDeleteItems(request); 149 return HandleDeleteItems(request);
146 case "GETITEM": 150 case "GETITEM":
147 return HandleGetItem(request); 151 return HandleGetItem(request);
152 case "GETMULTIPLEITEMS":
153 return HandleGetMultipleItems(request);
148 case "GETFOLDER": 154 case "GETFOLDER":
149 return HandleGetFolder(request); 155 return HandleGetFolder(request);
150 case "GETACTIVEGESTURES": 156 case "GETACTIVEGESTURES":
@@ -284,6 +290,8 @@ namespace OpenSim.Server.Handlers.Asset
284 InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID); 290 InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID);
285 if (icoll != null) 291 if (icoll != null)
286 { 292 {
293 result["FID"] = icoll.FolderID.ToString();
294 result["VERSION"] = icoll.Version.ToString();
287 Dictionary<string, object> folders = new Dictionary<string, object>(); 295 Dictionary<string, object> folders = new Dictionary<string, object>();
288 int i = 0; 296 int i = 0;
289 if (icoll.Folders != null) 297 if (icoll.Folders != null)
@@ -314,7 +322,71 @@ namespace OpenSim.Server.Handlers.Asset
314 return Util.UTF8NoBomEncoding.GetBytes(xmlString); 322 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
315 } 323 }
316 324
317 byte[] HandleGetFolderItems(Dictionary<string,object> request) 325 byte[] HandleGetMultipleFoldersContent(Dictionary<string, object> request)
326 {
327 Dictionary<string, object> resultSet = new Dictionary<string, object>();
328 UUID principal = UUID.Zero;
329 UUID.TryParse(request["PRINCIPAL"].ToString(), out principal);
330 string folderIDstr = request["FOLDERS"].ToString();
331 int count = 0;
332 Int32.TryParse(request["COUNT"].ToString(), out count);
333
334 UUID[] fids = new UUID[count];
335 string[] uuids = folderIDstr.Split(',');
336 int i = 0;
337 foreach (string id in uuids)
338 {
339 UUID fid = UUID.Zero;
340 if (UUID.TryParse(id, out fid))
341 fids[i] = fid;
342 i += 1;
343 }
344
345 count = 0;
346 InventoryCollection[] icollList = m_InventoryService.GetMultipleFoldersContent(principal, fids);
347 if (icollList != null && icollList.Length > 0)
348 {
349 foreach (InventoryCollection icoll in icollList)
350 {
351 Dictionary<string, object> result = new Dictionary<string, object>();
352 result["FID"] = icoll.FolderID.ToString();
353 result["VERSION"] = icoll.Version.ToString();
354 result["OWNER"] = icoll.OwnerID.ToString();
355 Dictionary<string, object> folders = new Dictionary<string, object>();
356 i = 0;
357 if (icoll.Folders != null)
358 {
359 foreach (InventoryFolderBase f in icoll.Folders)
360 {
361 folders["folder_" + i.ToString()] = EncodeFolder(f);
362 i++;
363 }
364 result["FOLDERS"] = folders;
365 }
366 i = 0;
367 if (icoll.Items != null)
368 {
369 Dictionary<string, object> items = new Dictionary<string, object>();
370 foreach (InventoryItemBase it in icoll.Items)
371 {
372 items["item_" + i.ToString()] = EncodeItem(it);
373 i++;
374 }
375 result["ITEMS"] = items;
376 }
377
378 resultSet["F_" + fids[count++]] = result;
379 //m_log.DebugFormat("[XXX]: Sending {0} {1}", fids[count-1], icoll.FolderID);
380 }
381 }
382
383 string xmlString = ServerUtils.BuildXmlResponse(resultSet);
384
385 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
386 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
387 }
388
389 byte[] HandleGetFolderItems(Dictionary<string, object> request)
318 { 390 {
319 Dictionary<string,object> result = new Dictionary<string,object>(); 391 Dictionary<string,object> result = new Dictionary<string,object>();
320 UUID principal = UUID.Zero; 392 UUID principal = UUID.Zero;
@@ -506,6 +578,40 @@ namespace OpenSim.Server.Handlers.Asset
506 return Util.UTF8NoBomEncoding.GetBytes(xmlString); 578 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
507 } 579 }
508 580
581 byte[] HandleGetMultipleItems(Dictionary<string, object> request)
582 {
583 Dictionary<string, object> resultSet = new Dictionary<string, object>();
584 UUID principal = UUID.Zero;
585 UUID.TryParse(request["PRINCIPAL"].ToString(), out principal);
586 string itemIDstr = request["ITEMS"].ToString();
587 int count = 0;
588 Int32.TryParse(request["COUNT"].ToString(), out count);
589
590 UUID[] fids = new UUID[count];
591 string[] uuids = itemIDstr.Split(',');
592 int i = 0;
593 foreach (string id in uuids)
594 {
595 UUID fid = UUID.Zero;
596 if (UUID.TryParse(id, out fid))
597 fids[i] = fid;
598 i += 1;
599 }
600
601 InventoryItemBase[] itemsList = m_InventoryService.GetMultipleItems(principal, fids);
602 if (itemsList != null && itemsList.Length > 0)
603 {
604 count = 0;
605 foreach (InventoryItemBase item in itemsList)
606 resultSet["item_" + count++] = (item == null) ? (object)"NULL" : EncodeItem(item);
607 }
608
609 string xmlString = ServerUtils.BuildXmlResponse(resultSet);
610
611 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
612 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
613 }
614
509 byte[] HandleGetFolder(Dictionary<string,object> request) 615 byte[] HandleGetFolder(Dictionary<string,object> request)
510 { 616 {
511 Dictionary<string, object> result = new Dictionary<string, object>(); 617 Dictionary<string, object> result = new Dictionary<string, object>();
diff --git a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
index 04fe41a..780e454 100644
--- a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Handlers/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/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
index a77d78e..21eb790 100644
--- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
@@ -257,8 +257,7 @@ namespace OpenSim.Server.Handlers.UserAccounts
257 257
258 byte[] CreateUser(Dictionary<string, object> request) 258 byte[] CreateUser(Dictionary<string, object> request)
259 { 259 {
260 if (! 260 if (! request.ContainsKey("FirstName")
261 request.ContainsKey("FirstName")
262 && request.ContainsKey("LastName") 261 && request.ContainsKey("LastName")
263 && request.ContainsKey("Password")) 262 && request.ContainsKey("Password"))
264 return FailureResult(); 263 return FailureResult();
diff --git a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
index 96391aa..9717319 100644
--- a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AssetService/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/Services/AuthenticationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
index 46fc1d5..8c63adc 100644
--- a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthenticationService/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/Services/AuthorizationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
index e04ea3f..ce91b56 100644
--- a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthorizationService/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/Services/AvatarService/Properties/AssemblyInfo.cs b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
index cf419ff..1778863 100644
--- a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AvatarService/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/Services/Base/Properties/AssemblyInfo.cs b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
index 328e011..a3fb11b 100644
--- a/OpenSim/Services/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Base/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/Services/Connectors/Estate/EstateDataConnector.cs b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
index 37f9374..6412bcd 100644
--- a/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
+++ b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
@@ -40,7 +40,7 @@ using OpenSim.Services.Connectors;
40using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSim.Server.Base; 41using OpenSim.Server.Base;
42 42
43namespace OpenSim.Service.Connectors 43namespace OpenSim.Services.Connectors
44{ 44{
45 public class EstateDataRemoteConnector : BaseServiceConnector, IEstateDataService 45 public class EstateDataRemoteConnector : BaseServiceConnector, IEstateDataService
46 { 46 {
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
index 574de89..db3c857 100644
--- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
@@ -205,7 +205,7 @@ namespace OpenSim.Services.Connectors
205 InventoryCollection inventory = new InventoryCollection(); 205 InventoryCollection inventory = new InventoryCollection();
206 inventory.Folders = new List<InventoryFolderBase>(); 206 inventory.Folders = new List<InventoryFolderBase>();
207 inventory.Items = new List<InventoryItemBase>(); 207 inventory.Items = new List<InventoryItemBase>();
208 inventory.UserID = principalID; 208 inventory.OwnerID = principalID;
209 209
210 try 210 try
211 { 211 {
@@ -235,6 +235,87 @@ namespace OpenSim.Services.Connectors
235 235
236 return inventory; 236 return inventory;
237 } 237 }
238
239 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
240 {
241 InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length];
242 //m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", folderIDs.Length);
243 try
244 {
245 Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT",
246 new Dictionary<string, object> {
247 { "PRINCIPAL", principalID.ToString() },
248 { "FOLDERS", String.Join(",", folderIDs) },
249 { "COUNT", folderIDs.Length.ToString() }
250 });
251
252 if (!CheckReturn(resultSet))
253 return null;
254
255 int i = 0;
256 foreach (KeyValuePair<string, object> kvp in resultSet)
257 {
258 InventoryCollection inventory = new InventoryCollection();
259 if (kvp.Key.StartsWith("F_"))
260 {
261 UUID fid = UUID.Zero;
262 if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i])
263 {
264 inventory.Folders = new List<InventoryFolderBase>();
265 inventory.Items = new List<InventoryItemBase>();
266
267 Dictionary<string, object> ret = (Dictionary<string, object>)kvp.Value;
268
269 if (ret.ContainsKey("FID"))
270 {
271 if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID))
272 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString());
273 }
274 else
275 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response");
276
277 inventory.Version = -1;
278 if (ret.ContainsKey("VERSION"))
279 Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version);
280 if (ret.ContainsKey("OWNER"))
281 UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID);
282
283 //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID);
284
285 Dictionary<string, object> folders =
286 (Dictionary<string, object>)ret["FOLDERS"];
287 Dictionary<string, object> items =
288 (Dictionary<string, object>)ret["ITEMS"];
289
290 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
291 {
292 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
293 }
294 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
295 {
296 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
297 }
298
299 inventoryArr[i] = inventory;
300 }
301 else
302 {
303 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}",
304 folderIDs[i], fid);
305 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys));
306 }
307
308 i += 1;
309 }
310 }
311 }
312 catch (Exception e)
313 {
314 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message);
315 }
316
317 return inventoryArr;
318 }
238 319
239 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 320 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
240 { 321 {
@@ -325,9 +406,13 @@ namespace OpenSim.Services.Connectors
325 406
326 public bool AddItem(InventoryItemBase item) 407 public bool AddItem(InventoryItemBase item)
327 { 408 {
409 if (item.Description == null)
410 item.Description = String.Empty;
328 if (item.CreatorData == null) 411 if (item.CreatorData == null)
329 item.CreatorData = String.Empty; 412 item.CreatorData = String.Empty;
330 Dictionary<string,object> ret = MakeRequest("ADDITEM", 413 if (item.CreatorId == null)
414 item.CreatorId = String.Empty;
415 Dictionary<string, object> ret = MakeRequest("ADDITEM",
331 new Dictionary<string,object> { 416 new Dictionary<string,object> {
332 { "AssetID", item.AssetID.ToString() }, 417 { "AssetID", item.AssetID.ToString() },
333 { "AssetType", item.AssetType.ToString() }, 418 { "AssetType", item.AssetType.ToString() },
@@ -446,6 +531,42 @@ namespace OpenSim.Services.Connectors
446 return null; 531 return null;
447 } 532 }
448 533
534 public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
535 {
536 InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length];
537 try
538 {
539 Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEITEMS",
540 new Dictionary<string, object> {
541 { "PRINCIPAL", principalID.ToString() },
542 { "ITEMS", String.Join(",", itemIDs) },
543 { "COUNT", itemIDs.Length.ToString() }
544 });
545
546 if (!CheckReturn(resultSet))
547 return null;
548
549 int i = 0;
550 foreach (KeyValuePair<string, object> kvp in resultSet)
551 {
552 InventoryCollection inventory = new InventoryCollection();
553 if (kvp.Key.StartsWith("item_"))
554 {
555 if (kvp.Value is Dictionary<string, object>)
556 itemArr[i++] = BuildItem((Dictionary<string, object>)kvp.Value);
557 else
558 itemArr[i++] = null;
559 }
560 }
561 }
562 catch (Exception e)
563 {
564 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message);
565 }
566
567 return itemArr;
568 }
569
449 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 570 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
450 { 571 {
451 try 572 try
diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
index bb78cfd..2af2ec1 100644
--- a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Connectors/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/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
index 9ded1c4..fdeea18 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
@@ -301,6 +301,21 @@ namespace OpenSim.Services.Connectors.SimianGrid
301 return null; 301 return null;
302 } 302 }
303 303
304 public InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
305 {
306 InventoryItemBase[] result = new InventoryItemBase[itemIDs.Length];
307 int i = 0;
308 InventoryItemBase item = new InventoryItemBase();
309 item.Owner = principalID;
310 foreach (UUID id in itemIDs)
311 {
312 item.ID = id;
313 result[i++] = GetItem(item);
314 }
315
316 return result;
317 }
318
304 /// <summary> 319 /// <summary>
305 /// Get a folder, given by its UUID 320 /// Get a folder, given by its UUID
306 /// </summary> 321 /// </summary>
@@ -340,7 +355,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
340 public InventoryCollection GetFolderContent(UUID userID, UUID folderID) 355 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
341 { 356 {
342 InventoryCollection inventory = new InventoryCollection(); 357 InventoryCollection inventory = new InventoryCollection();
343 inventory.UserID = userID; 358 inventory.OwnerID = userID;
344 359
345 NameValueCollection requestArgs = new NameValueCollection 360 NameValueCollection requestArgs = new NameValueCollection
346 { 361 {
@@ -371,6 +386,18 @@ namespace OpenSim.Services.Connectors.SimianGrid
371 return inventory; 386 return inventory;
372 } 387 }
373 388
389 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
390 {
391 InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
392 int i = 0;
393 foreach (UUID fid in folderIDs)
394 {
395 invColl[i++] = GetFolderContent(principalID, fid);
396 }
397
398 return invColl;
399 }
400
374 /// <summary> 401 /// <summary>
375 /// Gets the items inside a folder 402 /// Gets the items inside a folder
376 /// </summary> 403 /// </summary>
@@ -380,7 +407,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
380 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 407 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
381 { 408 {
382 InventoryCollection inventory = new InventoryCollection(); 409 InventoryCollection inventory = new InventoryCollection();
383 inventory.UserID = userID; 410 inventory.OwnerID = userID;
384 411
385 NameValueCollection requestArgs = new NameValueCollection 412 NameValueCollection requestArgs = new NameValueCollection
386 { 413 {
diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
index 3f61d9a..560e6c4 100644
--- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
+++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
@@ -215,9 +215,39 @@ namespace OpenSim.Services.Connectors
215 sendData[kvp.Key] = kvp.Value.ToString(); 215 sendData[kvp.Key] = kvp.Value.ToString();
216 } 216 }
217 217
218 return SendAndGetBoolReply(sendData); 218 if (SendAndGetReply(sendData) != null)
219 return true;
220 else
221 return false;
219 } 222 }
220 223
224 /// <summary>
225 /// Create user remotely. Note this this is not part of the IUserAccountsService
226 /// </summary>
227 /// <param name="first"></param>
228 /// <param name="last"></param>
229 /// <param name="password"></param>
230 /// <param name="email"></param>
231 /// <param name="scopeID"></param>
232 /// <returns></returns>
233 public virtual UserAccount CreateUser(string first, string last, string password, string email, UUID scopeID)
234 {
235 Dictionary<string, object> sendData = new Dictionary<string, object>();
236 //sendData["SCOPEID"] = scopeID.ToString();
237 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
238 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
239 sendData["METHOD"] = "createuser";
240
241 sendData["FirstName"] = first;
242 sendData["LastName"] = last;
243 sendData["Password"] = password;
244 if (!string.IsNullOrEmpty(email))
245 sendData["Email"] = first;
246 sendData["ScopeID"] = scopeID.ToString();
247
248 return SendAndGetReply(sendData);
249 }
250
221 private UserAccount SendAndGetReply(Dictionary<string, object> sendData) 251 private UserAccount SendAndGetReply(Dictionary<string, object> sendData)
222 { 252 {
223 string reply = string.Empty; 253 string reply = string.Empty;
@@ -260,7 +290,7 @@ namespace OpenSim.Services.Connectors
260 { 290 {
261 string reqString = ServerUtils.BuildQueryString(sendData); 291 string reqString = ServerUtils.BuildQueryString(sendData);
262 string uri = m_ServerURI + "/accounts"; 292 string uri = m_ServerURI + "/accounts";
263 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString); 293 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
264 try 294 try
265 { 295 {
266 string reply = SynchronousRestFormsRequester.MakeRequest("POST", 296 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
@@ -269,6 +299,7 @@ namespace OpenSim.Services.Connectors
269 m_Auth); 299 m_Auth);
270 if (reply != string.Empty) 300 if (reply != string.Empty)
271 { 301 {
302 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: reply = {0}", reply);
272 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply); 303 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
273 304
274 if (replyData.ContainsKey("result")) 305 if (replyData.ContainsKey("result"))
diff --git a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
index 3a50af3..ca16f08 100644
--- a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/FreeswitchService/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/Services/Friends/Properties/AssemblyInfo.cs b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
index d47e877..f258f94 100644
--- a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Friends/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/Services/GridService/Properties/AssemblyInfo.cs b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
index 6703b3c..ebe3c44 100644
--- a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/GridService/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/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs
index b57f8d8..a829932 100644
--- a/OpenSim/Services/HypergridService/HGAssetService.cs
+++ b/OpenSim/Services/HypergridService/HGAssetService.cs
@@ -163,7 +163,7 @@ namespace OpenSim.Services.HypergridService
163 protected byte[] AdjustIdentifiers(byte[] data) 163 protected byte[] AdjustIdentifiers(byte[] data)
164 { 164 {
165 string xml = Utils.BytesToString(data); 165 string xml = Utils.BytesToString(data);
166 return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, m_HomeURL, m_Cache, UUID.Zero)); 166 return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, "HGAssetService", m_HomeURL, m_Cache, UUID.Zero));
167 } 167 }
168 168
169 } 169 }
diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
index 9b7b278..32ca09a 100644
--- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs
+++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
@@ -101,7 +101,14 @@ namespace OpenSim.Services.HypergridService
101 Object[] args = new Object[] { config }; 101 Object[] args = new Object[] { config };
102 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); 102 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
103 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); 103 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
104 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(userAgentService, args); 104 try
105 {
106 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(userAgentService, args);
107 }
108 catch
109 {
110 m_log.WarnFormat("[HG IM SERVICE]: Unable to create User Agent Service. Missing config var in [HGInstantMessageService]?");
111 }
105 112
106 m_RegionCache = new ExpiringCache<UUID, GridRegion>(); 113 m_RegionCache = new ExpiringCache<UUID, GridRegion>();
107 114
diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs
index 2c63240..5f245e4 100644
--- a/OpenSim/Services/HypergridService/HGInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGInventoryService.cs
@@ -153,7 +153,14 @@ namespace OpenSim.Services.HypergridService
153 //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) 153 //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
154 //{ 154 //{
155 //} 155 //}
156 156
157 // NOGO
158 //
159 public override InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderID)
160 {
161 return new InventoryCollection[0];
162 }
163
157 //public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 164 //public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
158 //{ 165 //{
159 //} 166 //}
diff --git a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
index 5294a50..a565729 100644
--- a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/HypergridService/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/Services/Interfaces/IInventoryService.cs b/OpenSim/Services/Interfaces/IInventoryService.cs
index 2805356..1e8652c 100644
--- a/OpenSim/Services/Interfaces/IInventoryService.cs
+++ b/OpenSim/Services/Interfaces/IInventoryService.cs
@@ -76,6 +76,14 @@ namespace OpenSim.Services.Interfaces
76 /// <param name="folderID"></param> 76 /// <param name="folderID"></param>
77 /// <returns>Inventory content. null if the request failed.</returns> 77 /// <returns>Inventory content. null if the request failed.</returns>
78 InventoryCollection GetFolderContent(UUID userID, UUID folderID); 78 InventoryCollection GetFolderContent(UUID userID, UUID folderID);
79
80 /// <summary>
81 /// Gets everything (folders and items) inside a folder
82 /// </summary>
83 /// <param name="userId"></param>
84 /// <param name="folderIDs"></param>
85 /// <returns>Inventory content.</returns>
86 InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs);
79 87
80 /// <summary> 88 /// <summary>
81 /// Gets the items inside a folder 89 /// Gets the items inside a folder
@@ -156,6 +164,13 @@ namespace OpenSim.Services.Interfaces
156 InventoryItemBase GetItem(InventoryItemBase item); 164 InventoryItemBase GetItem(InventoryItemBase item);
157 165
158 /// <summary> 166 /// <summary>
167 /// Get multiple items, given by their UUIDs
168 /// </summary>
169 /// <param name="item"></param>
170 /// <returns>null if no item was found, otherwise the found item</returns>
171 InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] ids);
172
173 /// <summary>
159 /// Get a folder, given by its UUID 174 /// Get a folder, given by its UUID
160 /// </summary> 175 /// </summary>
161 /// <param name="folder"></param> 176 /// <param name="folder"></param>
diff --git a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
index b4fd068..a2f6c4f 100644
--- a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Interfaces/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/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
index 094e515..6a1187c 100644
--- a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/InventoryService/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/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 362ff8f..64f727c 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -261,7 +261,7 @@ namespace OpenSim.Services.InventoryService
261 261
262 private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type) 262 private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type)
263 { 263 {
264// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); 264 //m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0}", type);
265 265
266 if (type == AssetType.RootFolder) 266 if (type == AssetType.RootFolder)
267 return rootFolder; 267 return rootFolder;
@@ -272,13 +272,13 @@ namespace OpenSim.Services.InventoryService
272 272
273 if (folders.Length == 0) 273 if (folders.Length == 0)
274 { 274 {
275// m_log.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID); 275 //m_log.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} ", type);
276 return null; 276 return null;
277 } 277 }
278 278
279// m_log.DebugFormat( 279 //m_log.DebugFormat(
280// "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}", 280 // "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2}",
281// folders[0].folderName, folders[0].folderID, type, principalID); 281 // folders[0].folderName, folders[0].folderID, type);
282 282
283 return ConvertToOpenSim(folders[0]); 283 return ConvertToOpenSim(folders[0]);
284 } 284 }
@@ -291,7 +291,7 @@ namespace OpenSim.Services.InventoryService
291 // 291 //
292 //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); 292 //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString());
293 InventoryCollection inventory = new InventoryCollection(); 293 InventoryCollection inventory = new InventoryCollection();
294 inventory.UserID = principalID; 294 inventory.OwnerID = principalID;
295 inventory.Folders = new List<InventoryFolderBase>(); 295 inventory.Folders = new List<InventoryFolderBase>();
296 inventory.Items = new List<InventoryItemBase>(); 296 inventory.Items = new List<InventoryItemBase>();
297 297
@@ -315,8 +315,27 @@ namespace OpenSim.Services.InventoryService
315 inventory.Items.Add(ConvertToOpenSim(i)); 315 inventory.Items.Add(ConvertToOpenSim(i));
316 } 316 }
317 317
318 InventoryFolderBase f = new InventoryFolderBase(folderID, principalID);
319 f = GetFolder(f);
320 if (f != null)
321 {
322 inventory.Version = f.Version;
323 inventory.OwnerID = f.Owner;
324 }
325 inventory.FolderID = folderID;
326
318 return inventory; 327 return inventory;
319 } 328 }
329
330 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
331 {
332 InventoryCollection[] multiple = new InventoryCollection[folderIDs.Length];
333 int i = 0;
334 foreach (UUID fid in folderIDs)
335 multiple[i++] = GetFolderContent(principalID, fid);
336
337 return multiple;
338 }
320 339
321 public virtual List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 340 public virtual List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
322 { 341 {
@@ -591,6 +610,21 @@ namespace OpenSim.Services.InventoryService
591 return ConvertToOpenSim(items[0]); 610 return ConvertToOpenSim(items[0]);
592 } 611 }
593 612
613 public virtual InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] ids)
614 {
615 InventoryItemBase[] items = new InventoryItemBase[ids.Length];
616 int i = 0;
617 InventoryItemBase item = new InventoryItemBase();
618 item.Owner = userID;
619 foreach (UUID id in ids)
620 {
621 item.ID = id;
622 items[i++] = GetItem(item);
623 }
624
625 return items;
626 }
627
594 public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder) 628 public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder)
595 { 629 {
596 XInventoryFolder[] folders = m_Database.GetFolders( 630 XInventoryFolder[] folders = m_Database.GetFolders(
diff --git a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
index ea03b56..4dc492a 100644
--- a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/LLLoginService/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/Services/MapImageService/Properties/AssemblyInfo.cs b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
index 14dc990..e5f1bf9 100644
--- a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/MapImageService/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/Services/PresenceService/Properties/AssemblyInfo.cs b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
index ae122e4..9ef0ff3 100644
--- a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/PresenceService/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/Services/UserAccountService/Properties/AssemblyInfo.cs b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
index 9d031d0..33933a0 100644
--- a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/UserAccountService/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/Tests/Clients/Grid/GridClient.cs b/OpenSim/Tests/Clients/Grid/GridClient.cs
deleted file mode 100644
index fed7a16..0000000
--- a/OpenSim/Tests/Clients/Grid/GridClient.cs
+++ /dev/null
@@ -1,205 +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 System.Collections.Generic;
30using System.Text;
31using System.Reflection;
32
33using OpenMetaverse;
34using log4net;
35using log4net.Appender;
36using log4net.Layout;
37
38using OpenSim.Framework;
39using OpenSim.Services.Interfaces;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41using OpenSim.Services.Connectors;
42
43namespace OpenSim.Tests.Clients.GridClient
44{
45 public class GridClient
46 {
47// private static readonly ILog m_log =
48// LogManager.GetLogger(
49// MethodBase.GetCurrentMethod().DeclaringType);
50
51 public static void Main(string[] args)
52 {
53 ConsoleAppender consoleAppender = new ConsoleAppender();
54 consoleAppender.Layout =
55 new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline");
56 log4net.Config.BasicConfigurator.Configure(consoleAppender);
57
58 string serverURI = "http://127.0.0.1:8001";
59 GridServicesConnector m_Connector = new GridServicesConnector(serverURI);
60
61 GridRegion r1 = CreateRegion("Test Region 1", 1000, 1000);
62 GridRegion r2 = CreateRegion("Test Region 2", 1001, 1000);
63 GridRegion r3 = CreateRegion("Test Region 3", 1005, 1000);
64
65 Console.WriteLine("[GRID CLIENT]: *** Registering region 1");
66 string msg = m_Connector.RegisterRegion(UUID.Zero, r1);
67 if (msg == String.Empty)
68 Console.WriteLine("[GRID CLIENT]: Successfully registered region 1");
69 else
70 Console.WriteLine("[GRID CLIENT]: region 1 failed to register");
71
72 Console.WriteLine("[GRID CLIENT]: *** Registering region 2");
73 msg = m_Connector.RegisterRegion(UUID.Zero, r2);
74 if (msg == String.Empty)
75 Console.WriteLine("[GRID CLIENT]: Successfully registered region 2");
76 else
77 Console.WriteLine("[GRID CLIENT]: region 2 failed to register");
78
79 Console.WriteLine("[GRID CLIENT]: *** Registering region 3");
80 msg = m_Connector.RegisterRegion(UUID.Zero, r3);
81 if (msg == String.Empty)
82 Console.WriteLine("[GRID CLIENT]: Successfully registered region 3");
83 else
84 Console.WriteLine("[GRID CLIENT]: region 3 failed to register");
85
86
87 bool success;
88 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3");
89 success = m_Connector.DeregisterRegion(r3.RegionID);
90 if (success)
91 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3");
92 else
93 Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister");
94 Console.WriteLine("[GRID CLIENT]: *** Registering region 3 again");
95 msg = m_Connector.RegisterRegion(UUID.Zero, r3);
96 if (msg == String.Empty)
97 Console.WriteLine("[GRID CLIENT]: Successfully registered region 3");
98 else
99 Console.WriteLine("[GRID CLIENT]: region 3 failed to register");
100
101 Console.WriteLine("[GRID CLIENT]: *** GetNeighbours of region 1");
102 List<GridRegion> regions = m_Connector.GetNeighbours(UUID.Zero, r1.RegionID);
103 if (regions == null)
104 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 failed");
105 else if (regions.Count > 0)
106 {
107 if (regions.Count != 1)
108 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned more neighbours than expected: " + regions.Count);
109 else
110 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned the right neighbour " + regions[0].RegionName);
111 }
112 else
113 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned 0 neighbours");
114
115
116 Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of region 2 (this should succeed)");
117 GridRegion region = m_Connector.GetRegionByUUID(UUID.Zero, r2.RegionID);
118 if (region == null)
119 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null");
120 else
121 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName);
122
123 Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of non-existent region (this should fail)");
124 region = m_Connector.GetRegionByUUID(UUID.Zero, UUID.Random());
125 if (region == null)
126 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null");
127 else
128 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName);
129
130 Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of region 3 (this should succeed)");
131 region = m_Connector.GetRegionByName(UUID.Zero, r3.RegionName);
132 if (region == null)
133 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null");
134 else
135 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName);
136
137 Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of non-existent region (this should fail)");
138 region = m_Connector.GetRegionByName(UUID.Zero, "Foo");
139 if (region == null)
140 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null");
141 else
142 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName);
143
144 Console.WriteLine("[GRID CLIENT]: *** GetRegionsByName (this should return 3 regions)");
145 regions = m_Connector.GetRegionsByName(UUID.Zero, "Test", 10);
146 if (regions == null)
147 Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned null");
148 else
149 Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned " + regions.Count + " regions");
150
151 Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 2 regions)");
152 regions = m_Connector.GetRegionRange(UUID.Zero,
153 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002),
154 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) );
155 if (regions == null)
156 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
157 else
158 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions");
159 Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 0 regions)");
160 regions = m_Connector.GetRegionRange(UUID.Zero,
161 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950),
162 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) );
163 if (regions == null)
164 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
165 else
166 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions");
167
168 Console.Write("Proceed to deregister? Press enter...");
169 Console.ReadLine();
170
171 // Deregister them all
172 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 1");
173 success = m_Connector.DeregisterRegion(r1.RegionID);
174 if (success)
175 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 1");
176 else
177 Console.WriteLine("[GRID CLIENT]: region 1 failed to deregister");
178 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 2");
179 success = m_Connector.DeregisterRegion(r2.RegionID);
180 if (success)
181 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 2");
182 else
183 Console.WriteLine("[GRID CLIENT]: region 2 failed to deregister");
184 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3");
185 success = m_Connector.DeregisterRegion(r3.RegionID);
186 if (success)
187 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3");
188 else
189 Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister");
190
191 }
192
193 private static GridRegion CreateRegion(string name, uint xcell, uint ycell)
194 {
195 GridRegion region = new GridRegion(xcell, ycell);
196 region.RegionName = name;
197 region.RegionID = UUID.Random();
198 region.ExternalHostName = "127.0.0.1";
199 region.HttpPort = 9000;
200 region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 9000);
201
202 return region;
203 }
204 }
205}
diff --git a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini
deleted file mode 100644
index 8610c78..0000000
--- a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini
+++ /dev/null
@@ -1,33 +0,0 @@
1; * Run a ROBUST server shell like this, from bin:
2; * $ OpenSim.Server.exe -inifile ../OpenSim/Tests/Clients/Presence/OpenSim.Server.ini
3; *
4; * Then run this client like this, from bin:
5; * $ OpenSim.Tests.Clients.PresenceClient.exe
6; *
7; *
8
9[Startup]
10ServiceConnectors = "OpenSim.Server.Handlers.dll:PresenceServiceConnector"
11
12; * This is common for all services, it's the network setup for the entire
13; * server instance
14; *
15[Network]
16port = 8003
17
18; * The following are for the remote console
19; * They have no effect for the local or basic console types
20; * Leave commented to diable logins to the console
21;ConsoleUser = Test
22;ConsolePass = secret
23
24; * As an example, the below configuration precisely mimicks the legacy
25; * asset server. It is read by the asset IN connector (defined above)
26; * and it then loads the OUT connector (a local database module). That,
27; * in turn, reads the asset loader and database connection information
28; *
29[PresenceService]
30 LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService"
31 StorageProvider = "OpenSim.Data.MySQL.dll"
32 ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;"
33
diff --git a/OpenSim/Tests/Clients/Presence/PresenceClient.cs b/OpenSim/Tests/Clients/Presence/PresenceClient.cs
deleted file mode 100644
index fd3905a..0000000
--- a/OpenSim/Tests/Clients/Presence/PresenceClient.cs
+++ /dev/null
@@ -1,115 +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 System.Collections.Generic;
30using System.Text;
31using System.Reflection;
32
33using OpenMetaverse;
34using log4net;
35using log4net.Appender;
36using log4net.Layout;
37
38using OpenSim.Framework;
39using OpenSim.Services.Interfaces;
40using OpenSim.Services.Connectors;
41
42namespace OpenSim.Tests.Clients.PresenceClient
43{
44 public class PresenceClient
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 public static void Main(string[] args)
51 {
52 ConsoleAppender consoleAppender = new ConsoleAppender();
53 consoleAppender.Layout =
54 new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline");
55 log4net.Config.BasicConfigurator.Configure(consoleAppender);
56
57 string serverURI = "http://127.0.0.1:8003";
58 PresenceServicesConnector m_Connector = new PresenceServicesConnector(serverURI);
59
60 UUID user1 = UUID.Random();
61 UUID session1 = UUID.Random();
62 UUID region1 = UUID.Random();
63
64 bool success = m_Connector.LoginAgent(user1.ToString(), session1, UUID.Zero);
65 if (success)
66 m_log.InfoFormat("[PRESENCE CLIENT]: Successfully logged in user {0} with session {1}", user1, session1);
67 else
68 m_log.InfoFormat("[PRESENCE CLIENT]: failed to login user {0}", user1);
69
70 System.Console.WriteLine("\n");
71
72 PresenceInfo pinfo = m_Connector.GetAgent(session1);
73 if (pinfo == null)
74 m_log.InfoFormat("[PRESENCE CLIENT]: Unable to retrieve presence for {0}", user1);
75 else
76 m_log.InfoFormat("[PRESENCE CLIENT]: Presence retrieved correctly: userID={0}; regionID={1}",
77 pinfo.UserID, pinfo.RegionID);
78
79 System.Console.WriteLine("\n");
80 success = m_Connector.ReportAgent(session1, region1);
81 if (success)
82 m_log.InfoFormat("[PRESENCE CLIENT]: Successfully reported session {0} in region {1}", user1, region1);
83 else
84 m_log.InfoFormat("[PRESENCE CLIENT]: failed to report session {0}", session1);
85 pinfo = m_Connector.GetAgent(session1);
86 if (pinfo == null)
87 m_log.InfoFormat("[PRESENCE CLIENT]: Unable to retrieve presence for {0} for second time", user1);
88 else
89 m_log.InfoFormat("[PRESENCE CLIENT]: Presence retrieved correctly: userID={0}; regionID={2}",
90 pinfo.UserID, pinfo.RegionID);
91
92 System.Console.WriteLine("\n");
93 success = m_Connector.LogoutAgent(session1);
94 if (success)
95 m_log.InfoFormat("[PRESENCE CLIENT]: Successfully logged out user {0}", user1);
96 else
97 m_log.InfoFormat("[PRESENCE CLIENT]: failed to logout user {0}", user1);
98 pinfo = m_Connector.GetAgent(session1);
99 if (pinfo == null)
100 m_log.InfoFormat("[PRESENCE CLIENT]: Unable to retrieve presence for {0} for fourth time", user1);
101 else
102 m_log.InfoFormat("[PRESENCE CLIENT]: Presence retrieved correctly: userID={0}; regionID={1}",
103 pinfo.UserID, pinfo.RegionID);
104
105 System.Console.WriteLine("\n");
106 success = m_Connector.ReportAgent(session1, UUID.Random());
107 if (success)
108 m_log.InfoFormat("[PRESENCE CLIENT]: Report agent succeeded, but this is wrong");
109 else
110 m_log.InfoFormat("[PRESENCE CLIENT]: failed to report agent, as it should because user is not logged in");
111
112 }
113
114 }
115}
diff --git a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini
deleted file mode 100644
index 453e17e..0000000
--- a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini
+++ /dev/null
@@ -1,33 +0,0 @@
1; * Run a ROBUST server shell like this, from bin:
2; * $ OpenSim.Server.exe -inifile ../OpenSim/Tests/Clients/Presence/OpenSim.Server.ini
3; *
4; * Then run this client like this, from bin:
5; * $ OpenSim.Tests.Clients.UserAccountClient.exe
6; *
7; *
8
9[Startup]
10ServiceConnectors = "OpenSim.Server.Handlers.dll:UserAccountServiceConnector"
11
12; * This is common for all services, it's the network setup for the entire
13; * server instance
14; *
15[Network]
16port = 8003
17
18; * The following are for the remote console
19; * They have no effect for the local or basic console types
20; * Leave commented to diable logins to the console
21;ConsoleUser = Test
22;ConsolePass = secret
23
24; * As an example, the below configuration precisely mimicks the legacy
25; * asset server. It is read by the asset IN connector (defined above)
26; * and it then loads the OUT connector (a local database module). That,
27; * in turn, reads the asset loader and database connection information
28; *
29[UserAccountService]
30 LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService"
31 StorageProvider = "OpenSim.Data.MySQL.dll"
32 ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;"
33
diff --git a/OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs b/OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs
deleted file mode 100644
index 1e0a35b..0000000
--- a/OpenSim/Tests/Clients/UserAccounts/UserAccountsClient.cs
+++ /dev/null
@@ -1,144 +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 System.Collections.Generic;
30using System.Text;
31using System.Reflection;
32
33using OpenMetaverse;
34using log4net;
35using log4net.Appender;
36using log4net.Layout;
37
38using OpenSim.Framework;
39using OpenSim.Services.Interfaces;
40using OpenSim.Services.Connectors;
41
42namespace OpenSim.Tests.Clients.PresenceClient
43{
44 public class UserAccountsClient
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 public static void Main(string[] args)
51 {
52 ConsoleAppender consoleAppender = new ConsoleAppender();
53 consoleAppender.Layout =
54 new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline");
55 log4net.Config.BasicConfigurator.Configure(consoleAppender);
56
57 string serverURI = "http://127.0.0.1:8003";
58 UserAccountServicesConnector m_Connector = new UserAccountServicesConnector(serverURI);
59
60 UUID user1 = UUID.Random();
61 string first = "Completely";
62 string last = "Clueless";
63 string email = "foo@bar.com";
64
65 //UserAccount account = new UserAccount(user1);
66 //account.ScopeID = UUID.Zero;
67 //account.FirstName = first;
68 //account.LastName = last;
69 //account.Email = email;
70 //account.ServiceURLs = new Dictionary<string, object>();
71 //account.ServiceURLs.Add("InventoryServerURI", "http://cnn.com");
72 //account.ServiceURLs.Add("AssetServerURI", "http://cnn.com");
73
74 //bool success = m_Connector.StoreUserAccount(account);
75 //if (success)
76 // m_log.InfoFormat("[USER CLIENT]: Successfully created account for user {0} {1}", account.FirstName, account.LastName);
77 //else
78 // m_log.InfoFormat("[USER CLIENT]: failed to create user {0} {1}", account.FirstName, account.LastName);
79
80 //System.Console.WriteLine("\n");
81
82 //account = m_Connector.GetUserAccount(UUID.Zero, user1);
83 //if (account == null)
84 // m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by UUID for {0}", user1);
85 //else
86 //{
87 // m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}",
88 // account.PrincipalID, account.FirstName, account.LastName, account.Email);
89 // foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
90 // m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value);
91 //}
92
93 //System.Console.WriteLine("\n");
94
95 UserAccount account = m_Connector.GetUserAccount(UUID.Zero, first, last);
96 if (account == null)
97 m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by name ");
98 else
99 {
100 m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}",
101 account.PrincipalID, account.FirstName, account.LastName, account.Email);
102 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
103 m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value);
104 }
105
106 System.Console.WriteLine("\n");
107 account = m_Connector.GetUserAccount(UUID.Zero, email);
108 if (account == null)
109 m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by email");
110 else
111 {
112 m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}",
113 account.PrincipalID, account.FirstName, account.LastName, account.Email);
114 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
115 m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value);
116 }
117
118 System.Console.WriteLine("\n");
119 account = m_Connector.GetUserAccount(UUID.Zero, user1);
120 if (account == null)
121 m_log.InfoFormat("[USER CLIENT]: Unable to retrieve accouny by UUID for {0}", user1);
122 else
123 {
124 m_log.InfoFormat("[USER CLIENT]: Account retrieved correctly: userID={0}; FirstName={1}; LastName={2}; Email={3}",
125 account.PrincipalID, account.FirstName, account.LastName, account.Email);
126 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
127 m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value);
128 }
129
130 System.Console.WriteLine("\n");
131 account = m_Connector.GetUserAccount(UUID.Zero, "DoesNot", "Exist");
132 if (account == null)
133 m_log.InfoFormat("[USER CLIENT]: Unable to retrieve account 'DoesNot Exist'");
134 else
135 {
136 m_log.InfoFormat("[USER CLIENT]: Account 'DoesNot Exist' retrieved correctly. REALLY??? userID={0}; FirstName={1}; LastName={2}; Email={3}",
137 account.PrincipalID, account.FirstName, account.LastName, account.Email);
138 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
139 m_log.DebugFormat("\t {0} -> {1}", kvp.Key, kvp.Value);
140 }
141 }
142
143 }
144}
diff --git a/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs b/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs
new file mode 100644
index 0000000..671aca7
--- /dev/null
+++ b/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs
@@ -0,0 +1,133 @@
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.Text;
31using System.Reflection;
32
33using OpenMetaverse;
34using NUnit.Framework;
35
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Services.Connectors;
40
41namespace Robust.Tests
42{
43 [TestFixture]
44 public class GridClient
45 {
46// private static readonly ILog m_log =
47// LogManager.GetLogger(
48// MethodBase.GetCurrentMethod().DeclaringType);
49
50 [Test]
51 public void Grid_001()
52 {
53 GridServicesConnector m_Connector = new GridServicesConnector(DemonServer.Address);
54
55 GridRegion r1 = CreateRegion("Test Region 1", 1000, 1000);
56 GridRegion r2 = CreateRegion("Test Region 2", 1001, 1000);
57 GridRegion r3 = CreateRegion("Test Region 3", 1005, 1000);
58
59 string msg = m_Connector.RegisterRegion(UUID.Zero, r1);
60 Assert.AreEqual(msg, string.Empty, "Region 1 failed to register");
61
62 msg = m_Connector.RegisterRegion(UUID.Zero, r2);
63 Assert.AreEqual(msg, string.Empty, "Region 2 failed to register");
64
65 msg = m_Connector.RegisterRegion(UUID.Zero, r3);
66 Assert.AreEqual(msg, string.Empty, "Region 3 failed to register");
67
68 bool success;
69 success = m_Connector.DeregisterRegion(r3.RegionID);
70 Assert.AreEqual(success, true, "Region 3 failed to deregister");
71
72 msg = m_Connector.RegisterRegion(UUID.Zero, r3);
73 Assert.AreEqual(msg, string.Empty, "Region 3 failed to re-register");
74
75 List<GridRegion> regions = m_Connector.GetNeighbours(UUID.Zero, r1.RegionID);
76 Assert.AreNotEqual(regions, null, "GetNeighbours of region 1 failed");
77 Assert.AreEqual(regions.Count, 1, "Region 1 should have 1 neighbor");
78 Assert.AreEqual(regions[0].RegionName, "Test Region 2", "Region 1 has the wrong neighbor");
79
80 GridRegion region = m_Connector.GetRegionByUUID(UUID.Zero, r2.RegionID);
81 Assert.AreNotEqual(region, null, "GetRegionByUUID for region 2 failed");
82 Assert.AreEqual(region.RegionName, "Test Region 2", "GetRegionByUUID of region 2 returned wrong region");
83
84 region = m_Connector.GetRegionByUUID(UUID.Zero, UUID.Random());
85 Assert.AreEqual(region, null, "Region with randon id should not exist");
86
87 region = m_Connector.GetRegionByName(UUID.Zero, r3.RegionName);
88 Assert.AreNotEqual(region, null, "GetRegionByUUID for region 3 failed");
89 Assert.AreEqual(region.RegionName, "Test Region 3", "GetRegionByUUID of region 3 returned wrong region");
90
91 region = m_Connector.GetRegionByName(UUID.Zero, "Foo");
92 Assert.AreEqual(region, null, "Region Foo should not exist");
93
94 regions = m_Connector.GetRegionsByName(UUID.Zero, "Test", 10);
95 Assert.AreNotEqual(regions, null, "GetRegionsByName failed");
96 Assert.AreEqual(regions.Count, 3, "GetRegionsByName should return 3");
97
98 regions = m_Connector.GetRegionRange(UUID.Zero,
99 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002),
100 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) );
101 Assert.AreNotEqual(regions, null, "GetRegionRange failed");
102 Assert.AreEqual(regions.Count, 2, "GetRegionRange should return 2");
103
104 regions = m_Connector.GetRegionRange(UUID.Zero,
105 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950),
106 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) );
107 Assert.AreNotEqual(regions, null, "GetRegionRange (bis) failed");
108 Assert.AreEqual(regions.Count, 0, "GetRegionRange (bis) should return 0");
109
110 // Deregister them all
111 success = m_Connector.DeregisterRegion(r1.RegionID);
112 Assert.AreEqual(success, true, "Region 1 failed to deregister");
113
114 success = m_Connector.DeregisterRegion(r2.RegionID);
115 Assert.AreEqual(success, true, "Region 2 failed to deregister");
116
117 success = m_Connector.DeregisterRegion(r3.RegionID);
118 Assert.AreEqual(success, true, "Region 3 failed to deregister");
119 }
120
121 private static GridRegion CreateRegion(string name, uint xcell, uint ycell)
122 {
123 GridRegion region = new GridRegion(xcell, ycell);
124 region.RegionName = name;
125 region.RegionID = UUID.Random();
126 region.ExternalHostName = "127.0.0.1";
127 region.HttpPort = 9000;
128 region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 9000);
129
130 return region;
131 }
132 }
133}
diff --git a/OpenSim/Tests/Clients/Grid/GridForm.html b/OpenSim/Tests/Robust/Clients/Grid/GridForm.html
index 252920f..252920f 100644
--- a/OpenSim/Tests/Clients/Grid/GridForm.html
+++ b/OpenSim/Tests/Robust/Clients/Grid/GridForm.html
diff --git a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs
index e7304a2..8f312eb 100644
--- a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs
+++ b/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs
@@ -28,47 +28,30 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using System.Reflection;
32 31
33using OpenMetaverse; 32using OpenMetaverse;
34using log4net; 33using NUnit.Framework;
35using log4net.Appender;
36using log4net.Layout;
37 34
38using OpenSim.Framework; 35using OpenSim.Framework;
39using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
40using OpenSim.Services.Connectors.InstantMessage; 37using OpenSim.Services.Connectors.InstantMessage;
41 38
42namespace OpenSim.Tests.Clients.InstantMessage 39namespace Robust.Tests
43{ 40{
41 [TestFixture]
44 public class IMClient 42 public class IMClient
45 { 43 {
46 private static readonly ILog m_log = 44 [Test]
47 LogManager.GetLogger( 45 public void HGIM_001()
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 public static void Main(string[] args)
51 { 46 {
52 ConsoleAppender consoleAppender = new ConsoleAppender();
53 consoleAppender.Layout =
54 new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline");
55 log4net.Config.BasicConfigurator.Configure(consoleAppender);
56
57 string serverURI = "http://127.0.0.1:8002";
58 GridInstantMessage im = new GridInstantMessage(); 47 GridInstantMessage im = new GridInstantMessage();
59 im.fromAgentID = new Guid(); 48 im.fromAgentID = new Guid();
60 im.toAgentID = new Guid(); 49 im.toAgentID = new Guid();
61 im.message = "Hello"; 50 im.message = "Hello";
62 im.imSessionID = new Guid(); 51 im.imSessionID = new Guid();
63 52
64 bool success = InstantMessageServiceConnector.SendInstantMessage(serverURI, im); 53 bool success = InstantMessageServiceConnector.SendInstantMessage(DemonServer.Address, im);
65 54 Assert.IsFalse(success, "Sending of IM succeeded, but it should have failed");
66 if (success)
67 m_log.InfoFormat("[IM CLIENT]: Successfully IMed {0}", serverURI);
68 else
69 m_log.InfoFormat("[IM CLIENT]: failed to IM {0}", serverURI);
70
71 System.Console.WriteLine("\n");
72 } 55 }
73 56
74 } 57 }
diff --git a/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs b/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs
new file mode 100644
index 0000000..9d3f400
--- /dev/null
+++ b/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs
@@ -0,0 +1,153 @@
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.Text;
31using System.Reflection;
32
33using OpenMetaverse;
34using NUnit.Framework;
35
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38using OpenSim.Services.Connectors;
39
40namespace Robust.Tests
41{
42 [TestFixture]
43 public class InventoryClient
44 {
45// private static readonly ILog m_log =
46// LogManager.GetLogger(
47// MethodBase.GetCurrentMethod().DeclaringType);
48
49 private UUID m_userID = new UUID("00000000-0000-0000-0000-333333333333");
50 private UUID m_rootFolderID;
51 private UUID m_notecardsFolder;
52 private UUID m_objectsFolder;
53
54 [Test]
55 public void Inventory_001_CreateInventory()
56 {
57 XInventoryServicesConnector m_Connector = new XInventoryServicesConnector(DemonServer.Address);
58
59 // Create an inventory that looks like this:
60 //
61 // /My Inventory
62 // <other system folders>
63 // /Objects
64 // Some Object
65 // /Notecards
66 // Notecard 1
67 // Notecard 2
68 // /Test Folder
69 // Link to notecard -> /Notecards/Notecard 2
70 // Link to Objects folder -> /Objects
71
72 Console.WriteLine("Starting inventory test");
73 bool success = m_Connector.CreateUserInventory(m_userID);
74 Assert.IsTrue(success, "Failed to create user inventory");
75
76 m_rootFolderID = m_Connector.GetRootFolder(m_userID).ID;
77 Assert.AreNotEqual(m_rootFolderID, UUID.Zero, "Root folder ID must not be UUID.Zero");
78
79 InventoryFolderBase of = m_Connector.GetFolderForType(m_userID, AssetType.Object);
80 Assert.IsNotNull(of, "Failed to retrieve Objects folder");
81 m_objectsFolder = of.ID;
82 Assert.AreNotEqual(m_objectsFolder, UUID.Zero, "Objects folder ID must not be UUID.Zero");
83
84 // Add an object
85 InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID);
86 item.AssetID = UUID.Random();
87 item.AssetType = (int)AssetType.Object;
88 item.Folder = m_objectsFolder;
89 item.Name = "Some Object";
90 item.Description = string.Empty;
91 success = m_Connector.AddItem(item);
92 Assert.IsTrue(success, "Failed to add object to inventory");
93
94 InventoryFolderBase ncf = m_Connector.GetFolderForType(m_userID, AssetType.Notecard);
95 Assert.IsNotNull(of, "Failed to retrieve Notecards folder");
96 m_notecardsFolder = ncf.ID;
97 Assert.AreNotEqual(m_notecardsFolder, UUID.Zero, "Notecards folder ID must not be UUID.Zero");
98 m_notecardsFolder = ncf.ID;
99
100 // Add a notecard
101 item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID);
102 item.AssetID = UUID.Random();
103 item.AssetType = (int)AssetType.Notecard;
104 item.Folder = m_notecardsFolder;
105 item.Name = "Test Notecard 1";
106 item.Description = string.Empty;
107 success = m_Connector.AddItem(item);
108 Assert.IsTrue(success, "Failed to add Notecard 1 to inventory");
109 // Add another notecard
110 item.ID = new UUID("20000000-0000-0000-0000-000000000002");
111 item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a");
112 item.Name = "Test Notecard 2";
113 item.Description = string.Empty;
114 success = m_Connector.AddItem(item);
115 Assert.IsTrue(success, "Failed to add Notecard 2 to inventory");
116
117 // Add a folder
118 InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID);
119 folder.Type = (int)AssetType.Folder;
120 success = m_Connector.AddFolder(folder);
121 Assert.IsTrue(success, "Failed to add Test Folder to inventory");
122
123 // Add a link to notecard 2 in Test Folder
124 item.AssetID = item.ID; // use item ID of notecard 2
125 item.ID = new UUID("40000000-0000-0000-0000-000000000004");
126 item.AssetType = (int)AssetType.Link;
127 item.Folder = folder.ID;
128 item.Name = "Link to notecard";
129 item.Description = string.Empty;
130 success = m_Connector.AddItem(item);
131 Assert.IsTrue(success, "Failed to add link to notecard to inventory");
132
133 // Add a link to the Objects folder in Test Folder
134 item.AssetID = m_Connector.GetFolderForType(m_userID, AssetType.Object).ID; // use item ID of Objects folder
135 item.ID = new UUID("50000000-0000-0000-0000-000000000005");
136 item.AssetType = (int)AssetType.LinkFolder;
137 item.Folder = folder.ID;
138 item.Name = "Link to Objects folder";
139 item.Description = string.Empty;
140 success = m_Connector.AddItem(item);
141 Assert.IsTrue(success, "Failed to add link to objects folder to inventory");
142
143 InventoryCollection coll = m_Connector.GetFolderContent(m_userID, m_rootFolderID);
144 Assert.IsNotNull(coll, "Failed to retrieve contents of root folder");
145 Assert.Greater(coll.Folders.Count, 0, "Root folder does not have any subfolders");
146
147 coll = m_Connector.GetFolderContent(m_userID, folder.ID);
148 Assert.IsNotNull(coll, "Failed to retrieve contents of Test Folder");
149 Assert.AreEqual(coll.Items.Count + coll.Folders.Count, 2, "Test Folder is expected to have exactly 2 things inside");
150
151 }
152 }
153}
diff --git a/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs b/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs
new file mode 100644
index 0000000..31c8ee9
--- /dev/null
+++ b/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs
@@ -0,0 +1,81 @@
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.Text;
31using System.Reflection;
32
33using OpenMetaverse;
34using NUnit.Framework;
35
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38using OpenSim.Services.Connectors;
39
40namespace Robust.Tests
41{
42 [TestFixture]
43 public class PresenceClient
44 {
45 [Test]
46 public void Presence_001()
47 {
48 PresenceServicesConnector m_Connector = new PresenceServicesConnector(DemonServer.Address);
49
50 UUID user1 = UUID.Random();
51 UUID session1 = UUID.Random();
52 UUID region1 = UUID.Random();
53
54 bool success = m_Connector.LoginAgent(user1.ToString(), session1, UUID.Zero);
55 Assert.AreEqual(success, true, "Failed to add user session");
56
57 PresenceInfo pinfo = m_Connector.GetAgent(session1);
58 Assert.AreNotEqual(pinfo, null, "Unable to retrieve session");
59 Assert.AreEqual(pinfo.UserID, user1.ToString(), "Retrieved session does not match expected userID");
60 Assert.AreNotEqual(pinfo.RegionID, region1, "Retrieved session is unexpectedly in region");
61
62 success = m_Connector.ReportAgent(session1, region1);
63 Assert.AreEqual(success, true, "Failed to report session in region 1");
64
65 pinfo = m_Connector.GetAgent(session1);
66 Assert.AreNotEqual(pinfo, null, "Unable to session presence");
67 Assert.AreEqual(pinfo.UserID, user1.ToString(), "Retrieved session does not match expected userID");
68 Assert.AreEqual(pinfo.RegionID, region1, "Retrieved session is not in expected region");
69
70 success = m_Connector.LogoutAgent(session1);
71 Assert.AreEqual(success, true, "Failed to remove session");
72
73 pinfo = m_Connector.GetAgent(session1);
74 Assert.AreEqual(pinfo, null, "Session is still there, even though it shouldn't");
75
76 success = m_Connector.ReportAgent(session1, UUID.Random());
77 Assert.AreEqual(success, false, "Remove non-existing session should fail");
78 }
79
80 }
81}
diff --git a/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs b/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs
new file mode 100644
index 0000000..2c327e8
--- /dev/null
+++ b/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs
@@ -0,0 +1,85 @@
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.Text;
31using System.Reflection;
32
33using OpenMetaverse;
34using NUnit.Framework;
35
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38using OpenSim.Services.Connectors;
39
40namespace Robust.Tests
41{
42 [TestFixture]
43 public class UserAccountsClient
44 {
45 [Test]
46 public void UserAccounts_001()
47 {
48 UserAccountServicesConnector m_Connector = new UserAccountServicesConnector(DemonServer.Address);
49
50 string first = "Completely";
51 string last = "Clueless";
52 string email = "foo@bar.com";
53
54 UserAccount account = m_Connector.CreateUser(first, last, "123", email, UUID.Zero);
55 Assert.IsNotNull(account, "Failed to create account " + first + " " + last);
56 UUID user1 = account.PrincipalID;
57
58 account = m_Connector.GetUserAccount(UUID.Zero, user1);
59 Assert.NotNull(account, "Failed to retrieve account for user id " + user1);
60 Assert.AreEqual(account.FirstName, first, "First name does not match");
61 Assert.AreEqual(account.LastName, last, "Last name does not match");
62
63 account = m_Connector.GetUserAccount(UUID.Zero, first, last);
64 Assert.IsNotNull(account, "Failed to retrieve account for user " + first + " " + last);
65 Assert.AreEqual(account.FirstName, first, "First name does not match (bis)");
66 Assert.AreEqual(account.LastName, last, "Last name does not match (bis)");
67
68 account.Email = "user@example.com";
69 bool success = m_Connector.StoreUserAccount(account);
70 Assert.IsTrue(success, "Failed to store existing account");
71
72 account = m_Connector.GetUserAccount(UUID.Zero, user1);
73 Assert.NotNull(account, "Failed to retrieve account for user id " + user1);
74 Assert.AreEqual(account.Email, "user@example.com", "Incorrect email");
75
76 account = m_Connector.GetUserAccount(UUID.Zero, "DoesNot", "Exist");
77 Assert.IsNull(account, "Account DoesNot Exit must not be there");
78
79 account = new UserAccount(UUID.Zero, "DoesNot", "Exist", "xxx@xxx.com");
80 success = m_Connector.StoreUserAccount(account);
81 Assert.IsFalse(success, "Storing a non-existing account must fail");
82 }
83
84 }
85}
diff --git a/OpenSim/Tests/Robust/Server/DemonServer.cs b/OpenSim/Tests/Robust/Server/DemonServer.cs
new file mode 100644
index 0000000..1e0797e
--- /dev/null
+++ b/OpenSim/Tests/Robust/Server/DemonServer.cs
@@ -0,0 +1,69 @@
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.IO;
31using System.Threading;
32
33using Nini.Config;
34using log4net;
35using NUnit.Framework;
36
37using OpenSim.Server;
38
39namespace Robust.Tests
40{
41 [SetUpFixture]
42 public class DemonServer : OpenSimServer
43 {
44 private Thread m_demon;
45
46 public static string Address = "http://localhost:8888";
47
48 [SetUp]
49 public void StartDemon()
50 {
51 if (File.Exists("Robust.Tests.log"))
52 File.Delete("Robust.Tests.log");
53
54 Console.WriteLine("**** Starting demon Robust server ****");
55 m_demon = new Thread( () => Main(new string[] {"-inifile=Robust.Tests.ini"}));
56 m_demon.Start();
57 // Give some time for the server to instantiate all services
58 Thread.Sleep(3000);
59 Console.WriteLine("**** Setup Finished ****");
60 }
61
62 [TearDown]
63 public void StopDemon()
64 {
65 Console.WriteLine("**** Killing demon Robust Server ****");
66 m_Server.Shutdown();
67 }
68 }
69}
diff --git a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
index 7e92d76..b97c977 100644
--- a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Compiler/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/Tools/Configger/Properties/AssemblyInfo.cs b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
index c470703..e88f0f5 100644
--- a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Configger/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/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs
new file mode 100644
index 0000000..521415c
--- /dev/null
+++ b/OpenSim/Tools/pCampBot/Behaviours/InventoryDownloadBehaviour.cs
@@ -0,0 +1,121 @@
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 OpenMetaverse;
29using System;
30using System.Collections.Generic;
31using System.Diagnostics;
32using System.Threading;
33using System.Linq;
34using pCampBot.Interfaces;
35
36namespace pCampBot
37{
38 /// <summary>
39 /// Do nothing
40 /// </summary>
41 public class InventoryDownloadBehaviour : AbstractBehaviour
42 {
43 private bool m_initialized;
44 private int m_Requests = 2;
45 private Stopwatch m_StopWatch = new Stopwatch();
46 private List<UUID> m_processed = new List<UUID>();
47
48 public InventoryDownloadBehaviour()
49 {
50 AbbreviatedName = "inv";
51 Name = "Inventory";
52 }
53
54 public override void Action()
55 {
56 if (!m_initialized)
57 {
58 m_initialized = true;
59 Bot.Client.Settings.HTTP_INVENTORY = true;
60 Bot.Client.Settings.FETCH_MISSING_INVENTORY = true;
61 Bot.Client.Inventory.FolderUpdated += Inventory_FolderUpdated;
62 Console.WriteLine("Lib owner is " + Bot.Client.Inventory.Store.LibraryRootNode.Data.OwnerID);
63 m_StopWatch.Start();
64 Bot.Client.Inventory.RequestFolderContents(Bot.Client.Inventory.Store.RootFolder.UUID, Bot.Client.Self.AgentID, true, true, InventorySortOrder.ByDate);
65 Bot.Client.Inventory.RequestFolderContents(Bot.Client.Inventory.Store.LibraryRootNode.Data.UUID, Bot.Client.Inventory.Store.LibraryRootNode.Data.OwnerID, true, true, InventorySortOrder.ByDate);
66 }
67
68 Thread.Sleep(1000);
69 Console.WriteLine("Total items: " + Bot.Client.Inventory.Store.Items.Count + "; Total requests: " + m_Requests + "; Time: " + m_StopWatch.Elapsed);
70
71 }
72
73 void Inventory_FolderUpdated(object sender, FolderUpdatedEventArgs e)
74 {
75 if (e.Success)
76 {
77 //Console.WriteLine("Folder " + e.FolderID + " updated");
78 bool fetch = false;
79 lock (m_processed)
80 {
81 if (!m_processed.Contains(e.FolderID))
82 {
83 m_processed.Add(e.FolderID);
84 fetch = true;
85 }
86 }
87
88 if (fetch)
89 {
90 List<InventoryFolder> m_foldersToFetch = new List<InventoryFolder>();
91 foreach (InventoryBase item in Bot.Client.Inventory.Store.GetContents(e.FolderID))
92 {
93 if (item is InventoryFolder)
94 {
95 InventoryFolder f = new InventoryFolder(item.UUID);
96 f.OwnerID = item.OwnerID;
97 m_foldersToFetch.Add(f);
98 }
99 }
100 if (m_foldersToFetch.Count > 0)
101 {
102 m_Requests += 1;
103 Bot.Client.Inventory.RequestFolderContentsCap(m_foldersToFetch, Bot.Client.Network.CurrentSim.Caps.CapabilityURI("FetchInventoryDescendents2"), true, true, InventorySortOrder.ByDate);
104 }
105 }
106
107 if (Bot.Client.Inventory.Store.Items.Count >= 15739)
108 {
109 m_StopWatch.Stop();
110 Console.WriteLine("Stop! Total items: " + Bot.Client.Inventory.Store.Items.Count + "; Total requests: " + m_Requests + "; Time: " + m_StopWatch.Elapsed);
111 }
112 }
113
114 }
115
116 public override void Interrupt()
117 {
118 m_interruptEvent.Set();
119 }
120 }
121} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs
index 46094d6..0af9592 100644
--- a/OpenSim/Tools/pCampBot/BotManager.cs
+++ b/OpenSim/Tools/pCampBot/BotManager.cs
@@ -343,6 +343,9 @@ namespace pCampBot
343 if (abName == "ph2") 343 if (abName == "ph2")
344 newBehaviour = new PhysicsBehaviour2(); 344 newBehaviour = new PhysicsBehaviour2();
345 345
346 if (abName == "inv")
347 newBehaviour = new InventoryDownloadBehaviour();
348
346 if (newBehaviour != null) 349 if (newBehaviour != null)
347 { 350 {
348 behaviours.Add(newBehaviour); 351 behaviours.Add(newBehaviour);
diff --git a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
index c0c2b5d..87af19a 100644
--- a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/pCampBot/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