Merging Opensim upstream before generating patch
commit
140ea04b9d
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.Groups", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.OfflineIM", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -63,7 +63,7 @@ using Mono.Addins;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("0.7.6.*")]
|
// [assembly: AssemblyVersion("0.7.6.*")]
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.ApplicationPlugins.LoadRegions", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.ApplicationPlugins.RegionModulesController", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.ApplicationPlugins.RemoteController", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinDependency("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -0,0 +1,840 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Capabilities;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using Caps = OpenSim.Framework.Capabilities.Caps;
|
||||||
|
|
||||||
|
namespace OpenSim.Capabilities.Handlers
|
||||||
|
{
|
||||||
|
public class FetchInvDescHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IInventoryService m_InventoryService;
|
||||||
|
private ILibraryService m_LibraryService;
|
||||||
|
// private object m_fetchLock = new Object();
|
||||||
|
|
||||||
|
public FetchInvDescHandler(IInventoryService invService, ILibraryService libService)
|
||||||
|
{
|
||||||
|
m_InventoryService = invService;
|
||||||
|
m_LibraryService = libService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
|
||||||
|
// nasty temporary hack here, the linden client falsely
|
||||||
|
// identifies the uuid 00000000-0000-0000-0000-000000000000
|
||||||
|
// as a string which breaks us
|
||||||
|
//
|
||||||
|
// correctly mark it as a uuid
|
||||||
|
//
|
||||||
|
request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
|
||||||
|
|
||||||
|
// another hack <integer>1</integer> results in a
|
||||||
|
// System.ArgumentException: Object type System.Int32 cannot
|
||||||
|
// be converted to target type: System.Boolean
|
||||||
|
//
|
||||||
|
request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
|
||||||
|
request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
|
||||||
|
|
||||||
|
Hashtable hash = new Hashtable();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
|
||||||
|
}
|
||||||
|
catch (LLSD.LLSDParseException e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
|
||||||
|
m_log.Error("Request: " + request);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList foldersrequested = (ArrayList)hash["folders"];
|
||||||
|
|
||||||
|
string response = "";
|
||||||
|
string bad_folders_response = "";
|
||||||
|
|
||||||
|
List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
|
||||||
|
for (int i = 0; i < foldersrequested.Count; i++)
|
||||||
|
{
|
||||||
|
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
|
||||||
|
|
||||||
|
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter duplicate folder ids that bad viewers may send
|
||||||
|
if (folders.Find(f => f.folder_id == llsdRequest.folder_id) == null)
|
||||||
|
folders.Add(llsdRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (folders.Count > 0)
|
||||||
|
{
|
||||||
|
List<UUID> bad_folders = new List<UUID>();
|
||||||
|
List<InventoryCollectionWithDescendents> invcollSet = Fetch(folders, bad_folders);
|
||||||
|
//m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
|
||||||
|
|
||||||
|
if (invcollSet == null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Multiple folder fetch failed. Trying old protocol.");
|
||||||
|
return FetchInventoryDescendentsRequest(foldersrequested, httpRequest, httpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
string inventoryitemstr = string.Empty;
|
||||||
|
foreach (InventoryCollectionWithDescendents icoll in invcollSet)
|
||||||
|
{
|
||||||
|
LLSDInventoryDescendents reply = ToLLSD(icoll.Collection, icoll.Descendents);
|
||||||
|
|
||||||
|
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
|
||||||
|
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
|
||||||
|
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
|
||||||
|
|
||||||
|
response += inventoryitemstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
|
||||||
|
foreach (UUID bad in bad_folders)
|
||||||
|
bad_folders_response += "<uuid>" + bad + "</uuid>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Length == 0)
|
||||||
|
{
|
||||||
|
/* Viewers expect a bad_folders array when not available */
|
||||||
|
if (bad_folders_response.Length != 0)
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>folders</key><array /></map></llsd>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bad_folders_response.Length != 0)
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request for {0} folders. Item count {1}", folders.Count, item_count);
|
||||||
|
//m_log.Debug("[WEB FETCH INV DESC HANDLER] " + response);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct an LLSD reply packet to a CAPS inventory request
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="invFetch"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
|
||||||
|
{
|
||||||
|
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
|
||||||
|
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
|
||||||
|
contents.agent_id = invFetch.owner_id;
|
||||||
|
contents.owner_id = invFetch.owner_id;
|
||||||
|
contents.folder_id = invFetch.folder_id;
|
||||||
|
|
||||||
|
reply.folders.Array.Add(contents);
|
||||||
|
InventoryCollection inv = new InventoryCollection();
|
||||||
|
inv.Folders = new List<InventoryFolderBase>();
|
||||||
|
inv.Items = new List<InventoryItemBase>();
|
||||||
|
int version = 0;
|
||||||
|
int descendents = 0;
|
||||||
|
|
||||||
|
inv
|
||||||
|
= Fetch(
|
||||||
|
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
|
||||||
|
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
|
||||||
|
|
||||||
|
if (inv != null && inv.Folders != null)
|
||||||
|
{
|
||||||
|
foreach (InventoryFolderBase invFolder in inv.Folders)
|
||||||
|
{
|
||||||
|
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
|
||||||
|
}
|
||||||
|
|
||||||
|
descendents += inv.Folders.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inv != null && inv.Items != null)
|
||||||
|
{
|
||||||
|
foreach (InventoryItemBase invItem in inv.Items)
|
||||||
|
{
|
||||||
|
contents.items.Array.Add(ConvertInventoryItem(invItem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contents.descendents = descendents;
|
||||||
|
contents.version = version;
|
||||||
|
|
||||||
|
//m_log.DebugFormat(
|
||||||
|
// "[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}",
|
||||||
|
// invFetch.folder_id,
|
||||||
|
// invFetch.fetch_items,
|
||||||
|
// invFetch.fetch_folders,
|
||||||
|
// contents.items.Array.Count,
|
||||||
|
// contents.categories.Array.Count,
|
||||||
|
// invFetch.owner_id);
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents)
|
||||||
|
{
|
||||||
|
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
|
||||||
|
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
|
||||||
|
contents.agent_id = inv.OwnerID;
|
||||||
|
contents.owner_id = inv.OwnerID;
|
||||||
|
contents.folder_id = inv.FolderID;
|
||||||
|
|
||||||
|
reply.folders.Array.Add(contents);
|
||||||
|
|
||||||
|
if (inv.Folders != null)
|
||||||
|
{
|
||||||
|
foreach (InventoryFolderBase invFolder in inv.Folders)
|
||||||
|
{
|
||||||
|
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
|
||||||
|
}
|
||||||
|
|
||||||
|
descendents += inv.Folders.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inv.Items != null)
|
||||||
|
{
|
||||||
|
foreach (InventoryItemBase invItem in inv.Items)
|
||||||
|
{
|
||||||
|
contents.items.Array.Add(ConvertInventoryItem(invItem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contents.descendents = descendents;
|
||||||
|
contents.version = inv.Version;
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Old style. Soon to be deprecated.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="httpRequest"></param>
|
||||||
|
/// <param name="httpResponse"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Obsolete]
|
||||||
|
private string FetchInventoryDescendentsRequest(ArrayList foldersrequested, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request for {0} folders", foldersrequested.Count);
|
||||||
|
|
||||||
|
string response = "";
|
||||||
|
string bad_folders_response = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < foldersrequested.Count; i++)
|
||||||
|
{
|
||||||
|
string inventoryitemstr = "";
|
||||||
|
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
|
||||||
|
|
||||||
|
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
|
||||||
|
|
||||||
|
if (null == reply)
|
||||||
|
{
|
||||||
|
bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
|
||||||
|
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
|
||||||
|
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
response += inventoryitemstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Length == 0)
|
||||||
|
{
|
||||||
|
/* Viewers expect a bad_folders array when not available */
|
||||||
|
if (bad_folders_response.Length != 0)
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>folders</key><array /></map></llsd>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bad_folders_response.Length != 0)
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
|
||||||
|
//m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle the caps inventory descendents fetch.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agentID"></param>
|
||||||
|
/// <param name="folderID"></param>
|
||||||
|
/// <param name="ownerID"></param>
|
||||||
|
/// <param name="fetchFolders"></param>
|
||||||
|
/// <param name="fetchItems"></param>
|
||||||
|
/// <param name="sortOrder"></param>
|
||||||
|
/// <param name="version"></param>
|
||||||
|
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
|
||||||
|
[Obsolete]
|
||||||
|
private InventoryCollection Fetch(
|
||||||
|
UUID agentID, UUID folderID, UUID ownerID,
|
||||||
|
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
|
||||||
|
// fetchFolders, fetchItems, folderID, agentID);
|
||||||
|
|
||||||
|
// FIXME MAYBE: We're not handling sortOrder!
|
||||||
|
|
||||||
|
version = 0;
|
||||||
|
descendents = 0;
|
||||||
|
|
||||||
|
InventoryFolderImpl fold;
|
||||||
|
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
|
||||||
|
{
|
||||||
|
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
|
||||||
|
{
|
||||||
|
InventoryCollection ret = new InventoryCollection();
|
||||||
|
ret.Folders = new List<InventoryFolderBase>();
|
||||||
|
ret.Items = fold.RequestListOfItems();
|
||||||
|
descendents = ret.Folders.Count + ret.Items.Count;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryCollection contents = new InventoryCollection();
|
||||||
|
|
||||||
|
if (folderID != UUID.Zero)
|
||||||
|
{
|
||||||
|
InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
|
||||||
|
|
||||||
|
if (fetchedContents == null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
contents = fetchedContents;
|
||||||
|
InventoryFolderBase containingFolder = new InventoryFolderBase();
|
||||||
|
containingFolder.ID = folderID;
|
||||||
|
containingFolder.Owner = agentID;
|
||||||
|
containingFolder = m_InventoryService.GetFolder(containingFolder);
|
||||||
|
|
||||||
|
if (containingFolder != null)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
|
||||||
|
// containingFolder.Name, containingFolder.ID, agentID);
|
||||||
|
|
||||||
|
version = containingFolder.Version;
|
||||||
|
|
||||||
|
if (fetchItems)
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> itemsToReturn = contents.Items;
|
||||||
|
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
|
||||||
|
|
||||||
|
// descendents must only include the links, not the linked items we add
|
||||||
|
descendents = originalItems.Count;
|
||||||
|
|
||||||
|
// Add target items for links in this folder before the links themselves.
|
||||||
|
foreach (InventoryItemBase item in originalItems)
|
||||||
|
{
|
||||||
|
if (item.AssetType == (int)AssetType.Link)
|
||||||
|
{
|
||||||
|
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||||
|
|
||||||
|
// Take care of genuinely broken links where the target doesn't exist
|
||||||
|
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||||
|
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||||
|
// rather than having to keep track of every folder requested in the recursion.
|
||||||
|
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||||
|
itemsToReturn.Insert(0, linkedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now scan for folder links and insert the items they target and those links at the head of the return data
|
||||||
|
foreach (InventoryItemBase item in originalItems)
|
||||||
|
{
|
||||||
|
if (item.AssetType == (int)AssetType.LinkFolder)
|
||||||
|
{
|
||||||
|
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
|
||||||
|
List<InventoryItemBase> links = linkedFolderContents.Items;
|
||||||
|
|
||||||
|
itemsToReturn.InsertRange(0, links);
|
||||||
|
|
||||||
|
foreach (InventoryItemBase link in linkedFolderContents.Items)
|
||||||
|
{
|
||||||
|
// Take care of genuinely broken links where the target doesn't exist
|
||||||
|
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||||
|
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||||
|
// rather than having to keep track of every folder requested in the recursion.
|
||||||
|
if (link != null)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
|
||||||
|
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
|
||||||
|
|
||||||
|
InventoryItemBase linkedItem
|
||||||
|
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
|
||||||
|
|
||||||
|
if (linkedItem != null)
|
||||||
|
itemsToReturn.Insert(0, linkedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// foreach (InventoryItemBase item in contents.Items)
|
||||||
|
// {
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
|
||||||
|
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// =====
|
||||||
|
|
||||||
|
//
|
||||||
|
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
|
||||||
|
// {
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
|
||||||
|
// linkedItem.Name, folderID, agentID);
|
||||||
|
//
|
||||||
|
// contents.Items.Add(linkedItem);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
|
||||||
|
// // will be broken in the viewer.
|
||||||
|
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
|
||||||
|
// foreach (InventoryItemBase item in contents.Items)
|
||||||
|
// {
|
||||||
|
// if (item.AssetType == (int)AssetType.Link)
|
||||||
|
// {
|
||||||
|
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
||||||
|
//
|
||||||
|
// // Take care of genuinely broken links where the target doesn't exist
|
||||||
|
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||||
|
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||||
|
// // rather than having to keep track of every folder requested in the recursion.
|
||||||
|
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||||
|
// {
|
||||||
|
// // We don't need to send the folder if source and destination of the link are in the same
|
||||||
|
// // folder.
|
||||||
|
// if (linkedItem.Folder != containingFolder.ID)
|
||||||
|
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
|
||||||
|
// {
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
|
||||||
|
// linkedItemFolderId, folderID, agentID);
|
||||||
|
//
|
||||||
|
// int dummyVersion;
|
||||||
|
// InventoryCollection linkedCollection
|
||||||
|
// = Fetch(
|
||||||
|
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
|
||||||
|
//
|
||||||
|
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
|
||||||
|
// linkedFolder.Owner = agentID;
|
||||||
|
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
|
||||||
|
//
|
||||||
|
//// contents.Folders.AddRange(linkedCollection.Folders);
|
||||||
|
//
|
||||||
|
// contents.Folders.Add(linkedFolder);
|
||||||
|
// contents.Items.AddRange(linkedCollection.Items);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Lost items don't really need a version
|
||||||
|
version = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> fetchFolders, List<InventoryCollectionWithDescendents> result)
|
||||||
|
{
|
||||||
|
InventoryFolderImpl fold;
|
||||||
|
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
|
||||||
|
{
|
||||||
|
List<LLSDFetchInventoryDescendents> libfolders = fetchFolders.FindAll(f => f.owner_id == m_LibraryService.LibraryRootFolder.Owner);
|
||||||
|
fetchFolders.RemoveAll(f => libfolders.Contains(f));
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: Found {0} library folders in request", libfolders.Count);
|
||||||
|
|
||||||
|
foreach (LLSDFetchInventoryDescendents f in libfolders)
|
||||||
|
{
|
||||||
|
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(f.folder_id)) != null)
|
||||||
|
{
|
||||||
|
InventoryCollectionWithDescendents ret = new InventoryCollectionWithDescendents();
|
||||||
|
ret.Collection = new InventoryCollection();
|
||||||
|
ret.Collection.Folders = new List<InventoryFolderBase>();
|
||||||
|
ret.Collection.Items = fold.RequestListOfItems();
|
||||||
|
ret.Collection.OwnerID = m_LibraryService.LibraryRootFolder.Owner;
|
||||||
|
ret.Collection.FolderID = f.folder_id;
|
||||||
|
ret.Collection.Version = fold.Version;
|
||||||
|
|
||||||
|
ret.Descendents = ret.Collection.Items.Count;
|
||||||
|
result.Add(ret);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: Added libfolder {0} ({1}) {2}", ret.Collection.FolderID, ret.Collection.OwnerID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<InventoryCollectionWithDescendents> Fetch(List<LLSDFetchInventoryDescendents> fetchFolders, List<UUID> bad_folders)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Fetching {0} folders for owner {1}", fetchFolders.Count, fetchFolders[0].owner_id);
|
||||||
|
|
||||||
|
// FIXME MAYBE: We're not handling sortOrder!
|
||||||
|
|
||||||
|
List<InventoryCollectionWithDescendents> result = new List<InventoryCollectionWithDescendents>();
|
||||||
|
|
||||||
|
AddLibraryFolders(fetchFolders, result);
|
||||||
|
|
||||||
|
if (fetchFolders.Count > 0)
|
||||||
|
{
|
||||||
|
UUID[] fids = new UUID[fetchFolders.Count];
|
||||||
|
int i = 0;
|
||||||
|
foreach (LLSDFetchInventoryDescendents f in fetchFolders)
|
||||||
|
fids[i++] = f.folder_id;
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: {0}", string.Join(",", fids));
|
||||||
|
|
||||||
|
InventoryCollection[] fetchedContents = m_InventoryService.GetMultipleFoldersContent(fetchFolders[0].owner_id, fids);
|
||||||
|
|
||||||
|
if (fetchedContents == null || (fetchedContents != null && fetchedContents.Length == 0))
|
||||||
|
{
|
||||||
|
//m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of multiple folders for user {0}", fetchFolders[0].owner_id);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
// Do some post-processing. May need to fetch more from inv server for links
|
||||||
|
foreach (InventoryCollection contents in fetchedContents)
|
||||||
|
{
|
||||||
|
// Find the original request
|
||||||
|
LLSDFetchInventoryDescendents freq = fetchFolders[i++];
|
||||||
|
|
||||||
|
InventoryCollectionWithDescendents coll = new InventoryCollectionWithDescendents();
|
||||||
|
coll.Collection = contents;
|
||||||
|
|
||||||
|
if (BadFolder(freq, contents, bad_folders))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Next: link management
|
||||||
|
ProcessLinks(freq, coll);
|
||||||
|
|
||||||
|
result.Add(coll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool BadFolder(LLSDFetchInventoryDescendents freq, InventoryCollection contents, List<UUID> bad_folders)
|
||||||
|
{
|
||||||
|
bool bad = false;
|
||||||
|
if (contents == null)
|
||||||
|
{
|
||||||
|
bad_folders.Add(freq.folder_id);
|
||||||
|
bad = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The inventory server isn't sending FolderID in the collection...
|
||||||
|
// Must fetch it individually
|
||||||
|
if (contents.FolderID == UUID.Zero)
|
||||||
|
{
|
||||||
|
InventoryFolderBase containingFolder = new InventoryFolderBase();
|
||||||
|
containingFolder.ID = freq.folder_id;
|
||||||
|
containingFolder.Owner = freq.owner_id;
|
||||||
|
containingFolder = m_InventoryService.GetFolder(containingFolder);
|
||||||
|
|
||||||
|
if (containingFolder != null)
|
||||||
|
{
|
||||||
|
contents.FolderID = containingFolder.ID;
|
||||||
|
contents.OwnerID = containingFolder.Owner;
|
||||||
|
contents.Version = containingFolder.Version;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Was it really a request for folder Zero?
|
||||||
|
// This is an overkill, but Firestorm really asks for folder Zero.
|
||||||
|
// I'm leaving the code here for the time being, but commented.
|
||||||
|
if (freq.folder_id == UUID.Zero)
|
||||||
|
{
|
||||||
|
//coll.Collection.OwnerID = freq.owner_id;
|
||||||
|
//coll.Collection.FolderID = contents.FolderID;
|
||||||
|
//containingFolder = m_InventoryService.GetRootFolder(freq.owner_id);
|
||||||
|
//if (containingFolder != null)
|
||||||
|
//{
|
||||||
|
// m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Request for parent of folder {0}", containingFolder.ID);
|
||||||
|
// coll.Collection.Folders.Clear();
|
||||||
|
// coll.Collection.Folders.Add(containingFolder);
|
||||||
|
// if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null)
|
||||||
|
// {
|
||||||
|
// InventoryFolderBase lib = new InventoryFolderBase(m_LibraryService.LibraryRootFolder.ID, m_LibraryService.LibraryRootFolder.Owner);
|
||||||
|
// lib.Name = m_LibraryService.LibraryRootFolder.Name;
|
||||||
|
// lib.Type = m_LibraryService.LibraryRootFolder.Type;
|
||||||
|
// lib.Version = m_LibraryService.LibraryRootFolder.Version;
|
||||||
|
// coll.Collection.Folders.Add(lib);
|
||||||
|
// }
|
||||||
|
// coll.Collection.Items.Clear();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Unable to fetch folder {0}", freq.folder_id);
|
||||||
|
bad_folders.Add(freq.folder_id);
|
||||||
|
}
|
||||||
|
bad = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessLinks(LLSDFetchInventoryDescendents freq, InventoryCollectionWithDescendents coll)
|
||||||
|
{
|
||||||
|
InventoryCollection contents = coll.Collection;
|
||||||
|
|
||||||
|
if (freq.fetch_items && contents.Items != null)
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> itemsToReturn = contents.Items;
|
||||||
|
|
||||||
|
// descendents must only include the links, not the linked items we add
|
||||||
|
coll.Descendents = itemsToReturn.Count;
|
||||||
|
|
||||||
|
// Add target items for links in this folder before the links themselves.
|
||||||
|
List<UUID> itemIDs = new List<UUID>();
|
||||||
|
List<UUID> folderIDs = new List<UUID>();
|
||||||
|
foreach (InventoryItemBase item in itemsToReturn)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: {0} {1}", item.Name, item.AssetType);
|
||||||
|
if (item.AssetType == (int)AssetType.Link)
|
||||||
|
itemIDs.Add(item.AssetID);
|
||||||
|
|
||||||
|
else if (item.AssetType == (int)AssetType.LinkFolder)
|
||||||
|
folderIDs.Add(item.AssetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
|
||||||
|
|
||||||
|
// Scan for folder links and insert the items they target and those links at the head of the return data
|
||||||
|
if (folderIDs.Count > 0)
|
||||||
|
{
|
||||||
|
InventoryCollection[] linkedFolders = m_InventoryService.GetMultipleFoldersContent(coll.Collection.OwnerID, folderIDs.ToArray());
|
||||||
|
foreach (InventoryCollection linkedFolderContents in linkedFolders)
|
||||||
|
{
|
||||||
|
List<InventoryItemBase> links = linkedFolderContents.Items;
|
||||||
|
|
||||||
|
itemsToReturn.InsertRange(0, links);
|
||||||
|
|
||||||
|
foreach (InventoryItemBase link in linkedFolderContents.Items)
|
||||||
|
{
|
||||||
|
// Take care of genuinely broken links where the target doesn't exist
|
||||||
|
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||||
|
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||||
|
// rather than having to keep track of every folder requested in the recursion.
|
||||||
|
if (link != null)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat(
|
||||||
|
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})",
|
||||||
|
// link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID);
|
||||||
|
itemIDs.Add(link.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemIDs.Count > 0)
|
||||||
|
{
|
||||||
|
InventoryItemBase[] linked = m_InventoryService.GetMultipleItems(freq.owner_id, itemIDs.ToArray());
|
||||||
|
if (linked == null)
|
||||||
|
{
|
||||||
|
// OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
|
||||||
|
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
|
||||||
|
linked = new InventoryItemBase[itemIDs.Count];
|
||||||
|
int i = 0;
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.Owner = freq.owner_id;
|
||||||
|
foreach (UUID id in itemIDs)
|
||||||
|
{
|
||||||
|
item.ID = id;
|
||||||
|
linked[i++] = m_InventoryService.GetItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Processing folder {0}. Existing items:", freq.folder_id);
|
||||||
|
//foreach (InventoryItemBase item in itemsToReturn)
|
||||||
|
// m_log.DebugFormat("[XXX]: {0} {1} {2}", item.Name, item.AssetType, item.Folder);
|
||||||
|
|
||||||
|
if (linked != null)
|
||||||
|
{
|
||||||
|
foreach (InventoryItemBase linkedItem in linked)
|
||||||
|
{
|
||||||
|
// Take care of genuinely broken links where the target doesn't exist
|
||||||
|
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
||||||
|
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
||||||
|
// rather than having to keep track of every folder requested in the recursion.
|
||||||
|
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
||||||
|
{
|
||||||
|
itemsToReturn.Insert(0, linkedItem);
|
||||||
|
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Added {0} {1} {2}", linkedItem.Name, linkedItem.AssetType, linkedItem.Folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an internal inventory folder object into an LLSD object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="invFolder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
|
||||||
|
{
|
||||||
|
LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
|
||||||
|
llsdFolder.folder_id = invFolder.ID;
|
||||||
|
llsdFolder.parent_id = invFolder.ParentID;
|
||||||
|
llsdFolder.name = invFolder.Name;
|
||||||
|
llsdFolder.type = invFolder.Type;
|
||||||
|
llsdFolder.preferred_type = -1;
|
||||||
|
|
||||||
|
return llsdFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an internal inventory item object into an LLSD object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="invItem"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
|
||||||
|
{
|
||||||
|
LLSDInventoryItem llsdItem = new LLSDInventoryItem();
|
||||||
|
llsdItem.asset_id = invItem.AssetID;
|
||||||
|
llsdItem.created_at = invItem.CreationDate;
|
||||||
|
llsdItem.desc = invItem.Description;
|
||||||
|
llsdItem.flags = (int)invItem.Flags;
|
||||||
|
llsdItem.item_id = invItem.ID;
|
||||||
|
llsdItem.name = invItem.Name;
|
||||||
|
llsdItem.parent_id = invItem.Folder;
|
||||||
|
llsdItem.type = invItem.AssetType;
|
||||||
|
llsdItem.inv_type = invItem.InvType;
|
||||||
|
|
||||||
|
llsdItem.permissions = new LLSDPermissions();
|
||||||
|
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
|
||||||
|
llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
|
||||||
|
llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
|
||||||
|
llsdItem.permissions.group_id = invItem.GroupID;
|
||||||
|
llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
|
||||||
|
llsdItem.permissions.is_owner_group = invItem.GroupOwned;
|
||||||
|
llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
|
||||||
|
llsdItem.permissions.owner_id = invItem.Owner;
|
||||||
|
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
|
||||||
|
llsdItem.sale_info = new LLSDSaleInfo();
|
||||||
|
llsdItem.sale_info.sale_price = invItem.SalePrice;
|
||||||
|
llsdItem.sale_info.sale_type = invItem.SaleType;
|
||||||
|
|
||||||
|
return llsdItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InventoryCollectionWithDescendents
|
||||||
|
{
|
||||||
|
public InventoryCollection Collection;
|
||||||
|
public int Descendents;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using log4net;
|
||||||
|
using log4net.Config;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Capabilities.Handlers;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
|
|
||||||
|
namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase
|
||||||
|
{
|
||||||
|
private UUID m_userID = UUID.Zero;
|
||||||
|
private Scene m_scene;
|
||||||
|
private UUID m_rootFolderID;
|
||||||
|
private int m_rootDescendents;
|
||||||
|
private UUID m_notecardsFolder;
|
||||||
|
private UUID m_objectsFolder;
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
// Create an inventory that looks like this:
|
||||||
|
//
|
||||||
|
// /My Inventory
|
||||||
|
// <other system folders>
|
||||||
|
// /Objects
|
||||||
|
// Some Object
|
||||||
|
// /Notecards
|
||||||
|
// Notecard 1
|
||||||
|
// Notecard 2
|
||||||
|
// /Test Folder
|
||||||
|
// Link to notecard -> /Notecards/Notecard 2
|
||||||
|
// Link to Objects folder -> /Objects
|
||||||
|
|
||||||
|
m_scene = new SceneHelpers().SetupScene();
|
||||||
|
|
||||||
|
m_scene.InventoryService.CreateUserInventory(m_userID);
|
||||||
|
|
||||||
|
m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID;
|
||||||
|
|
||||||
|
InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Object);
|
||||||
|
m_objectsFolder = of.ID;
|
||||||
|
|
||||||
|
// Add an object
|
||||||
|
InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID);
|
||||||
|
item.AssetID = UUID.Random();
|
||||||
|
item.AssetType = (int)AssetType.Object;
|
||||||
|
item.Folder = m_objectsFolder;
|
||||||
|
item.Name = "Some Object";
|
||||||
|
m_scene.InventoryService.AddItem(item);
|
||||||
|
|
||||||
|
InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Notecard);
|
||||||
|
m_notecardsFolder = ncf.ID;
|
||||||
|
|
||||||
|
// Add a notecard
|
||||||
|
item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID);
|
||||||
|
item.AssetID = UUID.Random();
|
||||||
|
item.AssetType = (int)AssetType.Notecard;
|
||||||
|
item.Folder = m_notecardsFolder;
|
||||||
|
item.Name = "Test Notecard 1";
|
||||||
|
m_scene.InventoryService.AddItem(item);
|
||||||
|
// Add another notecard
|
||||||
|
item.ID = new UUID("20000000-0000-0000-0000-000000000002");
|
||||||
|
item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a");
|
||||||
|
item.Name = "Test Notecard 2";
|
||||||
|
m_scene.InventoryService.AddItem(item);
|
||||||
|
|
||||||
|
// Add a folder
|
||||||
|
InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID);
|
||||||
|
m_scene.InventoryService.AddFolder(folder);
|
||||||
|
|
||||||
|
// Add a link to notecard 2 in Test Folder
|
||||||
|
item.AssetID = item.ID; // use item ID of notecard 2
|
||||||
|
item.ID = new UUID("40000000-0000-0000-0000-000000000004");
|
||||||
|
item.AssetType = (int)AssetType.Link;
|
||||||
|
item.Folder = folder.ID;
|
||||||
|
item.Name = "Link to notecard";
|
||||||
|
m_scene.InventoryService.AddItem(item);
|
||||||
|
|
||||||
|
// Add a link to the Objects folder in Test Folder
|
||||||
|
item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, AssetType.Object).ID; // use item ID of Objects folder
|
||||||
|
item.ID = new UUID("50000000-0000-0000-0000-000000000005");
|
||||||
|
item.AssetType = (int)AssetType.LinkFolder;
|
||||||
|
item.Folder = folder.ID;
|
||||||
|
item.Name = "Link to Objects folder";
|
||||||
|
m_scene.InventoryService.AddItem(item);
|
||||||
|
|
||||||
|
InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID);
|
||||||
|
m_rootDescendents = coll.Items.Count + coll.Folders.Count;
|
||||||
|
Console.WriteLine("Number of descendents: " + m_rootDescendents);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_001_SimpleFolder()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
Init();
|
||||||
|
|
||||||
|
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null);
|
||||||
|
TestOSHttpRequest req = new TestOSHttpRequest();
|
||||||
|
TestOSHttpResponse resp = new TestOSHttpResponse();
|
||||||
|
|
||||||
|
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>";
|
||||||
|
request += m_rootFolderID;
|
||||||
|
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
|
||||||
|
|
||||||
|
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
|
||||||
|
|
||||||
|
Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
|
||||||
|
Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
|
||||||
|
Assert.That(llsdresponse.Contains("00000000-0000-0000-0000-000000000000"), Is.True, "Response should contain userID");
|
||||||
|
|
||||||
|
string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
|
||||||
|
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents");
|
||||||
|
Console.WriteLine(llsdresponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_002_MultipleFolders()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null);
|
||||||
|
TestOSHttpRequest req = new TestOSHttpRequest();
|
||||||
|
TestOSHttpResponse resp = new TestOSHttpResponse();
|
||||||
|
|
||||||
|
string request = "<llsd><map><key>folders</key><array>";
|
||||||
|
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
|
||||||
|
request += m_rootFolderID;
|
||||||
|
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
|
||||||
|
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
|
||||||
|
request += m_notecardsFolder;
|
||||||
|
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
|
||||||
|
request += "</array></map></llsd>";
|
||||||
|
|
||||||
|
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
|
||||||
|
Console.WriteLine(llsdresponse);
|
||||||
|
|
||||||
|
string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
|
||||||
|
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder");
|
||||||
|
descendents = "descendents</key><integer>2</integer>";
|
||||||
|
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder");
|
||||||
|
|
||||||
|
Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response");
|
||||||
|
Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_003_Links()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null);
|
||||||
|
TestOSHttpRequest req = new TestOSHttpRequest();
|
||||||
|
TestOSHttpResponse resp = new TestOSHttpResponse();
|
||||||
|
|
||||||
|
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>";
|
||||||
|
request += "f0000000-0000-0000-0000-00000000000f";
|
||||||
|
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
|
||||||
|
|
||||||
|
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp);
|
||||||
|
Console.WriteLine(llsdresponse);
|
||||||
|
|
||||||
|
string descendents = "descendents</key><integer>2</integer>";
|
||||||
|
Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder");
|
||||||
|
|
||||||
|
// Make sure that the note card link is included
|
||||||
|
Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing");
|
||||||
|
|
||||||
|
//Make sure the notecard item itself is included
|
||||||
|
Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing");
|
||||||
|
|
||||||
|
// Make sure that the source item is before the link item
|
||||||
|
int pos1 = llsdresponse.IndexOf("Test Notecard 2");
|
||||||
|
int pos2 = llsdresponse.IndexOf("Link to notecard");
|
||||||
|
Assert.Less(pos1, pos2, "Source of link is after link");
|
||||||
|
|
||||||
|
// Make sure the folder link is included
|
||||||
|
Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing");
|
||||||
|
|
||||||
|
// Make sure the objects inside the Objects folder are included
|
||||||
|
// Note: I'm not entirely sure this is needed, but that's what I found in the implementation
|
||||||
|
Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing");
|
||||||
|
|
||||||
|
// Make sure that the source item is before the link item
|
||||||
|
pos1 = llsdresponse.IndexOf("Some Object");
|
||||||
|
pos2 = llsdresponse.IndexOf("Link to Objects folder");
|
||||||
|
Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,465 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of the OpenSimulator Project nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using log4net;
|
|
||||||
using Nini.Config;
|
|
||||||
using OpenMetaverse;
|
|
||||||
using OpenMetaverse.StructuredData;
|
|
||||||
using OpenSim.Framework;
|
|
||||||
using OpenSim.Framework.Capabilities;
|
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
|
||||||
using OpenSim.Framework.Servers.HttpServer;
|
|
||||||
using OpenSim.Services.Interfaces;
|
|
||||||
using Caps = OpenSim.Framework.Capabilities.Caps;
|
|
||||||
|
|
||||||
namespace OpenSim.Capabilities.Handlers
|
|
||||||
{
|
|
||||||
public class FetchInvDescHandler
|
|
||||||
{
|
|
||||||
private static readonly ILog m_log =
|
|
||||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
|
|
||||||
private IInventoryService m_InventoryService;
|
|
||||||
private ILibraryService m_LibraryService;
|
|
||||||
// private object m_fetchLock = new Object();
|
|
||||||
|
|
||||||
public FetchInvDescHandler(IInventoryService invService, ILibraryService libService)
|
|
||||||
{
|
|
||||||
m_InventoryService = invService;
|
|
||||||
m_LibraryService = libService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
|
||||||
{
|
|
||||||
// lock (m_fetchLock)
|
|
||||||
// {
|
|
||||||
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request);
|
|
||||||
|
|
||||||
// nasty temporary hack here, the linden client falsely
|
|
||||||
// identifies the uuid 00000000-0000-0000-0000-000000000000
|
|
||||||
// as a string which breaks us
|
|
||||||
//
|
|
||||||
// correctly mark it as a uuid
|
|
||||||
//
|
|
||||||
request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
|
|
||||||
|
|
||||||
// another hack <integer>1</integer> results in a
|
|
||||||
// System.ArgumentException: Object type System.Int32 cannot
|
|
||||||
// be converted to target type: System.Boolean
|
|
||||||
//
|
|
||||||
request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
|
|
||||||
request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
|
|
||||||
|
|
||||||
Hashtable hash = new Hashtable();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
|
|
||||||
}
|
|
||||||
catch (LLSD.LLSDParseException e)
|
|
||||||
{
|
|
||||||
m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
|
|
||||||
m_log.Error("Request: " + request);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList foldersrequested = (ArrayList)hash["folders"];
|
|
||||||
|
|
||||||
string response = "";
|
|
||||||
string bad_folders_response = "";
|
|
||||||
|
|
||||||
for (int i = 0; i < foldersrequested.Count; i++)
|
|
||||||
{
|
|
||||||
string inventoryitemstr = "";
|
|
||||||
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
|
|
||||||
|
|
||||||
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
|
|
||||||
}
|
|
||||||
LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
|
|
||||||
|
|
||||||
if (null == reply)
|
|
||||||
{
|
|
||||||
bad_folders_response += "<uuid>" + llsdRequest.folder_id.ToString() + "</uuid>";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
|
|
||||||
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
|
|
||||||
inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
response += inventoryitemstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.Length == 0)
|
|
||||||
{
|
|
||||||
/* Viewers expect a bad_folders array when not available */
|
|
||||||
if (bad_folders_response.Length != 0)
|
|
||||||
{
|
|
||||||
response = "<llsd><map><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response = "<llsd><map><key>folders</key><array /></map></llsd>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (bad_folders_response.Length != 0)
|
|
||||||
{
|
|
||||||
response = "<llsd><map><key>folders</key><array>" + response + "</array><key>bad_folders</key><array>" + bad_folders_response + "</array></map></llsd>";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
|
|
||||||
//m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Construct an LLSD reply packet to a CAPS inventory request
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="invFetch"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
|
|
||||||
{
|
|
||||||
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
|
|
||||||
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
|
|
||||||
contents.agent_id = invFetch.owner_id;
|
|
||||||
contents.owner_id = invFetch.owner_id;
|
|
||||||
contents.folder_id = invFetch.folder_id;
|
|
||||||
|
|
||||||
reply.folders.Array.Add(contents);
|
|
||||||
InventoryCollection inv = new InventoryCollection();
|
|
||||||
inv.Folders = new List<InventoryFolderBase>();
|
|
||||||
inv.Items = new List<InventoryItemBase>();
|
|
||||||
int version = 0;
|
|
||||||
int descendents = 0;
|
|
||||||
|
|
||||||
inv
|
|
||||||
= Fetch(
|
|
||||||
invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
|
|
||||||
invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
|
|
||||||
|
|
||||||
if (inv != null && inv.Folders != null)
|
|
||||||
{
|
|
||||||
foreach (InventoryFolderBase invFolder in inv.Folders)
|
|
||||||
{
|
|
||||||
contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
|
|
||||||
}
|
|
||||||
|
|
||||||
descendents += inv.Folders.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inv != null && inv.Items != null)
|
|
||||||
{
|
|
||||||
foreach (InventoryItemBase invItem in inv.Items)
|
|
||||||
{
|
|
||||||
contents.items.Array.Add(ConvertInventoryItem(invItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contents.descendents = descendents;
|
|
||||||
contents.version = version;
|
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[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}",
|
|
||||||
// invFetch.folder_id,
|
|
||||||
// invFetch.fetch_items,
|
|
||||||
// invFetch.fetch_folders,
|
|
||||||
// contents.items.Array.Count,
|
|
||||||
// contents.categories.Array.Count,
|
|
||||||
// invFetch.owner_id);
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handle the caps inventory descendents fetch.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="agentID"></param>
|
|
||||||
/// <param name="folderID"></param>
|
|
||||||
/// <param name="ownerID"></param>
|
|
||||||
/// <param name="fetchFolders"></param>
|
|
||||||
/// <param name="fetchItems"></param>
|
|
||||||
/// <param name="sortOrder"></param>
|
|
||||||
/// <param name="version"></param>
|
|
||||||
/// <returns>An empty InventoryCollection if the inventory look up failed</returns>
|
|
||||||
private InventoryCollection Fetch(
|
|
||||||
UUID agentID, UUID folderID, UUID ownerID,
|
|
||||||
bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
|
|
||||||
{
|
|
||||||
//m_log.DebugFormat(
|
|
||||||
// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
|
|
||||||
// fetchFolders, fetchItems, folderID, agentID);
|
|
||||||
|
|
||||||
// FIXME MAYBE: We're not handling sortOrder!
|
|
||||||
|
|
||||||
version = 0;
|
|
||||||
descendents = 0;
|
|
||||||
|
|
||||||
InventoryFolderImpl fold;
|
|
||||||
if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
|
|
||||||
{
|
|
||||||
if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
|
|
||||||
{
|
|
||||||
InventoryCollection ret = new InventoryCollection();
|
|
||||||
ret.Folders = new List<InventoryFolderBase>();
|
|
||||||
ret.Items = fold.RequestListOfItems();
|
|
||||||
descendents = ret.Folders.Count + ret.Items.Count;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InventoryCollection contents = new InventoryCollection();
|
|
||||||
|
|
||||||
if (folderID != UUID.Zero)
|
|
||||||
{
|
|
||||||
InventoryCollection fetchedContents = m_InventoryService.GetFolderContent(agentID, folderID);
|
|
||||||
|
|
||||||
if (fetchedContents == null)
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("[WEB FETCH INV DESC HANDLER]: Could not get contents of folder {0} for user {1}", folderID, agentID);
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
contents = fetchedContents;
|
|
||||||
InventoryFolderBase containingFolder = new InventoryFolderBase();
|
|
||||||
containingFolder.ID = folderID;
|
|
||||||
containingFolder.Owner = agentID;
|
|
||||||
containingFolder = m_InventoryService.GetFolder(containingFolder);
|
|
||||||
|
|
||||||
if (containingFolder != null)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
|
|
||||||
// containingFolder.Name, containingFolder.ID, agentID);
|
|
||||||
|
|
||||||
version = containingFolder.Version;
|
|
||||||
|
|
||||||
if (fetchItems)
|
|
||||||
{
|
|
||||||
List<InventoryItemBase> itemsToReturn = contents.Items;
|
|
||||||
List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
|
|
||||||
|
|
||||||
// descendents must only include the links, not the linked items we add
|
|
||||||
descendents = originalItems.Count;
|
|
||||||
|
|
||||||
// Add target items for links in this folder before the links themselves.
|
|
||||||
foreach (InventoryItemBase item in originalItems)
|
|
||||||
{
|
|
||||||
if (item.AssetType == (int)AssetType.Link)
|
|
||||||
{
|
|
||||||
InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
|
||||||
|
|
||||||
// Take care of genuinely broken links where the target doesn't exist
|
|
||||||
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
|
||||||
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
|
||||||
// rather than having to keep track of every folder requested in the recursion.
|
|
||||||
if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
|
||||||
itemsToReturn.Insert(0, linkedItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now scan for folder links and insert the items they target and those links at the head of the return data
|
|
||||||
foreach (InventoryItemBase item in originalItems)
|
|
||||||
{
|
|
||||||
if (item.AssetType == (int)AssetType.LinkFolder)
|
|
||||||
{
|
|
||||||
InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
|
|
||||||
List<InventoryItemBase> links = linkedFolderContents.Items;
|
|
||||||
|
|
||||||
itemsToReturn.InsertRange(0, links);
|
|
||||||
|
|
||||||
foreach (InventoryItemBase link in linkedFolderContents.Items)
|
|
||||||
{
|
|
||||||
// Take care of genuinely broken links where the target doesn't exist
|
|
||||||
// HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
|
||||||
// but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
|
||||||
// rather than having to keep track of every folder requested in the recursion.
|
|
||||||
if (link != null)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
|
|
||||||
// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
|
|
||||||
|
|
||||||
InventoryItemBase linkedItem
|
|
||||||
= m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
|
|
||||||
|
|
||||||
if (linkedItem != null)
|
|
||||||
itemsToReturn.Insert(0, linkedItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// foreach (InventoryItemBase item in contents.Items)
|
|
||||||
// {
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
|
|
||||||
// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// =====
|
|
||||||
|
|
||||||
//
|
|
||||||
// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
|
|
||||||
// {
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
|
|
||||||
// linkedItem.Name, folderID, agentID);
|
|
||||||
//
|
|
||||||
// contents.Items.Add(linkedItem);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // If the folder requested contains links, then we need to send those folders first, otherwise the links
|
|
||||||
// // will be broken in the viewer.
|
|
||||||
// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
|
|
||||||
// foreach (InventoryItemBase item in contents.Items)
|
|
||||||
// {
|
|
||||||
// if (item.AssetType == (int)AssetType.Link)
|
|
||||||
// {
|
|
||||||
// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
|
|
||||||
//
|
|
||||||
// // Take care of genuinely broken links where the target doesn't exist
|
|
||||||
// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
|
|
||||||
// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
|
|
||||||
// // rather than having to keep track of every folder requested in the recursion.
|
|
||||||
// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
|
|
||||||
// {
|
|
||||||
// // We don't need to send the folder if source and destination of the link are in the same
|
|
||||||
// // folder.
|
|
||||||
// if (linkedItem.Folder != containingFolder.ID)
|
|
||||||
// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
|
|
||||||
// {
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
|
|
||||||
// linkedItemFolderId, folderID, agentID);
|
|
||||||
//
|
|
||||||
// int dummyVersion;
|
|
||||||
// InventoryCollection linkedCollection
|
|
||||||
// = Fetch(
|
|
||||||
// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
|
|
||||||
//
|
|
||||||
// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
|
|
||||||
// linkedFolder.Owner = agentID;
|
|
||||||
// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
|
|
||||||
//
|
|
||||||
//// contents.Folders.AddRange(linkedCollection.Folders);
|
|
||||||
//
|
|
||||||
// contents.Folders.Add(linkedFolder);
|
|
||||||
// contents.Items.AddRange(linkedCollection.Items);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Lost items don't really need a version
|
|
||||||
version = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return contents;
|
|
||||||
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// Convert an internal inventory folder object into an LLSD object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="invFolder"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
|
|
||||||
{
|
|
||||||
LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
|
|
||||||
llsdFolder.folder_id = invFolder.ID;
|
|
||||||
llsdFolder.parent_id = invFolder.ParentID;
|
|
||||||
llsdFolder.name = invFolder.Name;
|
|
||||||
llsdFolder.type = invFolder.Type;
|
|
||||||
llsdFolder.preferred_type = -1;
|
|
||||||
|
|
||||||
return llsdFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert an internal inventory item object into an LLSD object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="invItem"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
|
|
||||||
{
|
|
||||||
LLSDInventoryItem llsdItem = new LLSDInventoryItem();
|
|
||||||
llsdItem.asset_id = invItem.AssetID;
|
|
||||||
llsdItem.created_at = invItem.CreationDate;
|
|
||||||
llsdItem.desc = invItem.Description;
|
|
||||||
llsdItem.flags = (int)invItem.Flags;
|
|
||||||
llsdItem.item_id = invItem.ID;
|
|
||||||
llsdItem.name = invItem.Name;
|
|
||||||
llsdItem.parent_id = invItem.Folder;
|
|
||||||
llsdItem.type = invItem.AssetType;
|
|
||||||
llsdItem.inv_type = invItem.InvType;
|
|
||||||
|
|
||||||
llsdItem.permissions = new LLSDPermissions();
|
|
||||||
llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
|
|
||||||
llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
|
|
||||||
llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
|
|
||||||
llsdItem.permissions.group_id = invItem.GroupID;
|
|
||||||
llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
|
|
||||||
llsdItem.permissions.is_owner_group = invItem.GroupOwned;
|
|
||||||
llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
|
|
||||||
llsdItem.permissions.owner_id = invItem.Owner;
|
|
||||||
llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
|
|
||||||
llsdItem.sale_info = new LLSDSaleInfo();
|
|
||||||
llsdItem.sale_info.sale_price = invItem.SalePrice;
|
|
||||||
llsdItem.sale_info.sale_type = invItem.SaleType;
|
|
||||||
|
|
||||||
return llsdItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -59,4 +59,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all values by your own or you can build default build and revision
|
// You can specify all values by your own or you can build default build and revision
|
||||||
// numbers with the '*' character (the default):
|
// numbers with the '*' character (the default):
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
public List<InventoryFolderBase> Folders;
|
public List<InventoryFolderBase> Folders;
|
||||||
public List<InventoryItemBase> Items;
|
public List<InventoryItemBase> Items;
|
||||||
public UUID UserID;
|
public UUID OwnerID;
|
||||||
|
public UUID FolderID;
|
||||||
|
public int Version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,8 @@ namespace OpenSim.Framework.Serialization.External
|
||||||
/// <param name="userService">The service for retrieving user account information</param>
|
/// <param name="userService">The service for retrieving user account information</param>
|
||||||
/// <param name="scopeID">The scope of the user account information (Grid ID)</param>
|
/// <param name="scopeID">The scope of the user account information (Grid ID)</param>
|
||||||
/// <returns>The SceneObjectPart represented in XML2</returns>
|
/// <returns>The SceneObjectPart represented in XML2</returns>
|
||||||
public static string RewriteSOP(string xml, string homeURL, IUserAccountService userService, UUID scopeID)
|
[Obsolete("This method is deprecated. Use RewriteSOP instead.")]
|
||||||
|
public static string RewriteSOP_Old(string xml, string homeURL, IUserAccountService userService, UUID scopeID)
|
||||||
{
|
{
|
||||||
if (xml == string.Empty || homeURL == string.Empty || userService == null)
|
if (xml == string.Empty || homeURL == string.Empty || userService == null)
|
||||||
return xml;
|
return xml;
|
||||||
|
@ -173,6 +174,187 @@ namespace OpenSim.Framework.Serialization.External
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Takes a XML representation of a SceneObjectPart and returns another XML representation
|
||||||
|
/// with creator data added to it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="xml">The SceneObjectPart represented in XML2</param>
|
||||||
|
/// <param name="sceneName">An identifier for the component that's calling this function</param>
|
||||||
|
/// <param name="homeURL">The URL of the user agents service (home) for the creator</param>
|
||||||
|
/// <param name="userService">The service for retrieving user account information</param>
|
||||||
|
/// <param name="scopeID">The scope of the user account information (Grid ID)</param>
|
||||||
|
/// <returns>The SceneObjectPart represented in XML2</returns>
|
||||||
|
public static string RewriteSOP(string xmlData, string sceneName, string homeURL, IUserAccountService userService, UUID scopeID)
|
||||||
|
{
|
||||||
|
// Console.WriteLine("Input XML [{0}]", xmlData);
|
||||||
|
if (xmlData == string.Empty || homeURL == string.Empty || userService == null)
|
||||||
|
return xmlData;
|
||||||
|
|
||||||
|
using (StringWriter sw = new StringWriter())
|
||||||
|
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
||||||
|
using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
|
||||||
|
using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment }))
|
||||||
|
{
|
||||||
|
TransformXml(reader, writer, sceneName, homeURL, userService, scopeID);
|
||||||
|
|
||||||
|
// Console.WriteLine("Output: [{0}]", sw.ToString());
|
||||||
|
|
||||||
|
return sw.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void TransformXml(XmlReader reader, XmlWriter writer, string sceneName, string homeURI, IUserAccountService userAccountService, UUID scopeID)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML");
|
||||||
|
|
||||||
|
int sopDepth = -1;
|
||||||
|
UserAccount creator = null;
|
||||||
|
bool hasCreatorData = false;
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
// Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name);
|
||||||
|
|
||||||
|
switch (reader.NodeType)
|
||||||
|
{
|
||||||
|
case XmlNodeType.Attribute:
|
||||||
|
// Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name);
|
||||||
|
writer.WriteAttributeString(reader.Name, reader.Value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.CDATA:
|
||||||
|
writer.WriteCData(reader.Value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.Comment:
|
||||||
|
writer.WriteComment(reader.Value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.DocumentType:
|
||||||
|
writer.WriteDocType(reader.Name, reader.Value, null, null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.Element:
|
||||||
|
// m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name);
|
||||||
|
|
||||||
|
writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
|
||||||
|
|
||||||
|
if (reader.HasAttributes)
|
||||||
|
{
|
||||||
|
while (reader.MoveToNextAttribute())
|
||||||
|
writer.WriteAttributeString(reader.Name, reader.Value);
|
||||||
|
|
||||||
|
reader.MoveToElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.LocalName == "SceneObjectPart")
|
||||||
|
{
|
||||||
|
if (sopDepth < 0)
|
||||||
|
{
|
||||||
|
sopDepth = reader.Depth;
|
||||||
|
// m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sopDepth >= 0 && reader.Depth == sopDepth + 1)
|
||||||
|
{
|
||||||
|
if (reader.Name == "CreatorID")
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID")
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
if (reader.NodeType == XmlNodeType.Text)
|
||||||
|
{
|
||||||
|
UUID uuid = UUID.Zero;
|
||||||
|
UUID.TryParse(reader.Value, out uuid);
|
||||||
|
creator = userAccountService.GetUserAccount(scopeID, uuid);
|
||||||
|
writer.WriteElementString("UUID", reader.Value);
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we unexpected run across mixed content in this node, still carry on
|
||||||
|
// transforming the subtree (this replicates earlier behaviour).
|
||||||
|
TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we unexpected run across mixed content in this node, still carry on
|
||||||
|
// transforming the subtree (this replicates earlier behaviour).
|
||||||
|
TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (reader.Name == "CreatorData")
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
if (reader.NodeType == XmlNodeType.Text)
|
||||||
|
{
|
||||||
|
hasCreatorData = true;
|
||||||
|
writer.WriteString(reader.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we unexpected run across mixed content in this node, still carry on
|
||||||
|
// transforming the subtree (this replicates earlier behaviour).
|
||||||
|
TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name);
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.EndElement:
|
||||||
|
// m_log.DebugFormat("Depth {0} at EndElement", reader.Depth);
|
||||||
|
if (sopDepth == reader.Depth)
|
||||||
|
{
|
||||||
|
if (!hasCreatorData && creator != null)
|
||||||
|
writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", homeURI, creator.FirstName, creator.LastName));
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth");
|
||||||
|
sopDepth = -1;
|
||||||
|
creator = null;
|
||||||
|
hasCreatorData = false;
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.EntityReference:
|
||||||
|
writer.WriteEntityRef(reader.Name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.ProcessingInstruction:
|
||||||
|
writer.WriteProcessingInstruction(reader.Name, reader.Value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.Text:
|
||||||
|
writer.WriteString(reader.Value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.XmlDeclaration:
|
||||||
|
// For various reasons, not all serializations have xml declarations (or consistent ones)
|
||||||
|
// and as it's embedded inside a byte stream we don't need it anyway, so ignore.
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}",
|
||||||
|
reader.NodeType, sceneName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string CalcCreatorData(string homeURL, string name)
|
public static string CalcCreatorData(string homeURL, string name)
|
||||||
{
|
{
|
||||||
return homeURL + ";" + name;
|
return homeURL + ";" + name;
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -292,11 +292,11 @@ namespace OpenSim.Framework.Servers
|
||||||
+ " 3 = full stack trace, including common threads\n",
|
+ " 3 = full stack trace, including common threads\n",
|
||||||
HandleDebugThreadpoolLevel);
|
HandleDebugThreadpoolLevel);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
// m_console.Commands.AddCommand(
|
||||||
"Debug", false, "show threadpool calls active",
|
// "Debug", false, "show threadpool calls active",
|
||||||
"show threadpool calls active",
|
// "show threadpool calls active",
|
||||||
"Show details about threadpool calls that are still active (currently waiting or in progress)",
|
// "Show details about threadpool calls that are still active (currently waiting or in progress)",
|
||||||
HandleShowThreadpoolCallsActive);
|
// HandleShowThreadpoolCallsActive);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Debug", false, "show threadpool calls complete",
|
"Debug", false, "show threadpool calls complete",
|
||||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: AddinRoot("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinRoot("OpenSim", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: ImportAddinAssembly("OpenSim.Framework.dll")]
|
[assembly: ImportAddinAssembly("OpenSim.Framework.dll")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -201,11 +201,12 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
Scene.EventManager.OnRegisterCaps += RegisterCaps;
|
Scene.EventManager.OnRegisterCaps += RegisterCaps;
|
||||||
|
|
||||||
|
int nworkers = 2; // was 2
|
||||||
if (ProcessQueuedRequestsAsync && m_workerThreads == null)
|
if (ProcessQueuedRequestsAsync && m_workerThreads == null)
|
||||||
{
|
{
|
||||||
m_workerThreads = new Thread[2];
|
m_workerThreads = new Thread[nworkers];
|
||||||
|
|
||||||
for (uint i = 0; i < 2; i++)
|
for (uint i = 0; i < nworkers; i++)
|
||||||
{
|
{
|
||||||
m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests,
|
m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests,
|
||||||
String.Format("InventoryWorkerThread{0}", i),
|
String.Format("InventoryWorkerThread{0}", i),
|
||||||
|
@ -364,7 +365,11 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
|
requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
|
||||||
|
|
||||||
lock (responses)
|
lock (responses)
|
||||||
|
{
|
||||||
|
if (responses.ContainsKey(requestID))
|
||||||
|
m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054");
|
||||||
responses[requestID] = response;
|
responses[requestID] = response;
|
||||||
|
}
|
||||||
|
|
||||||
WebFetchInvDescModule.ProcessedRequestsCount++;
|
WebFetchInvDescModule.ProcessedRequestsCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3747,6 +3747,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
avp.Sender.IsTrial = false;
|
avp.Sender.IsTrial = false;
|
||||||
avp.Sender.ID = agentID;
|
avp.Sender.ID = agentID;
|
||||||
avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
|
avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
|
||||||
|
avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0];
|
||||||
//m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
|
//m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
|
||||||
OutPacket(avp, ThrottleOutPacketType.Task);
|
OutPacket(avp, ThrottleOutPacketType.Task);
|
||||||
}
|
}
|
||||||
|
@ -4465,7 +4466,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
uint priority = 0; // time based ordering only
|
uint priority = 0; // time based ordering only
|
||||||
lock (m_entityProps.SyncRoot)
|
lock (m_entityProps.SyncRoot)
|
||||||
m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
|
m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResendPropertyUpdate(ObjectPropertyUpdate update)
|
private void ResendPropertyUpdate(ObjectPropertyUpdate update)
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ using System.Xml;
|
||||||
using log4net;
|
using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Serialization.External;
|
||||||
|
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Region.Framework.Scenes.Serialization;
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
@ -189,217 +190,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
return Utils.StringToBytes(RewriteSOP(xml));
|
return Utils.StringToBytes(RewriteSOP(xml));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void TransformXml(XmlReader reader, XmlWriter writer)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML");
|
|
||||||
|
|
||||||
int sopDepth = -1;
|
|
||||||
UserAccount creator = null;
|
|
||||||
bool hasCreatorData = false;
|
|
||||||
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
// Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name);
|
|
||||||
|
|
||||||
switch (reader.NodeType)
|
|
||||||
{
|
|
||||||
case XmlNodeType.Attribute:
|
|
||||||
// Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name);
|
|
||||||
writer.WriteAttributeString(reader.Prefix, reader.Name, reader.NamespaceURI, reader.Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.CDATA:
|
|
||||||
writer.WriteCData(reader.Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.Comment:
|
|
||||||
writer.WriteComment(reader.Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.DocumentType:
|
|
||||||
writer.WriteDocType(reader.Name, reader.Value, null, null);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.Element:
|
|
||||||
// m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name);
|
|
||||||
|
|
||||||
writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
|
|
||||||
|
|
||||||
if (reader.HasAttributes)
|
|
||||||
{
|
|
||||||
while (reader.MoveToNextAttribute())
|
|
||||||
writer.WriteAttributeString(reader.Prefix, reader.Name, reader.NamespaceURI, reader.Value);
|
|
||||||
|
|
||||||
reader.MoveToElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reader.LocalName == "SceneObjectPart")
|
|
||||||
{
|
|
||||||
if (sopDepth < 0)
|
|
||||||
{
|
|
||||||
sopDepth = reader.Depth;
|
|
||||||
// m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (sopDepth >= 0 && reader.Depth == sopDepth + 1)
|
|
||||||
{
|
|
||||||
if (reader.Name == "CreatorID")
|
|
||||||
{
|
|
||||||
reader.Read();
|
|
||||||
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID")
|
|
||||||
{
|
|
||||||
reader.Read();
|
|
||||||
|
|
||||||
if (reader.NodeType == XmlNodeType.Text)
|
|
||||||
{
|
|
||||||
UUID uuid = UUID.Zero;
|
|
||||||
UUID.TryParse(reader.Value, out uuid);
|
|
||||||
creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
|
|
||||||
writer.WriteElementString("UUID", reader.Value);
|
|
||||||
reader.Read();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we unexpected run across mixed content in this node, still carry on
|
|
||||||
// transforming the subtree (this replicates earlier behaviour).
|
|
||||||
TransformXml(reader, writer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we unexpected run across mixed content in this node, still carry on
|
|
||||||
// transforming the subtree (this replicates earlier behaviour).
|
|
||||||
TransformXml(reader, writer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (reader.Name == "CreatorData")
|
|
||||||
{
|
|
||||||
reader.Read();
|
|
||||||
if (reader.NodeType == XmlNodeType.Text)
|
|
||||||
{
|
|
||||||
hasCreatorData = true;
|
|
||||||
writer.WriteString(reader.Value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we unexpected run across mixed content in this node, still carry on
|
|
||||||
// transforming the subtree (this replicates earlier behaviour).
|
|
||||||
TransformXml(reader, writer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reader.IsEmptyElement)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name);
|
|
||||||
writer.WriteEndElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.EndElement:
|
|
||||||
// m_log.DebugFormat("Depth {0} at EndElement", reader.Depth);
|
|
||||||
if (sopDepth == reader.Depth)
|
|
||||||
{
|
|
||||||
if (!hasCreatorData && creator != null)
|
|
||||||
writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", m_HomeURI, creator.FirstName, creator.LastName));
|
|
||||||
|
|
||||||
// m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth");
|
|
||||||
sopDepth = -1;
|
|
||||||
creator = null;
|
|
||||||
hasCreatorData = false;
|
|
||||||
}
|
|
||||||
writer.WriteEndElement();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.EntityReference:
|
|
||||||
writer.WriteEntityRef(reader.Name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.ProcessingInstruction:
|
|
||||||
writer.WriteProcessingInstruction(reader.Name, reader.Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.Text:
|
|
||||||
writer.WriteString(reader.Value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XmlNodeType.XmlDeclaration:
|
|
||||||
// For various reasons, not all serializations have xml declarations (or consistent ones)
|
|
||||||
// and as it's embedded inside a byte stream we don't need it anyway, so ignore.
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
m_log.WarnFormat(
|
|
||||||
"[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}",
|
|
||||||
reader.NodeType, m_scene.Name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected string RewriteSOP(string xmlData)
|
protected string RewriteSOP(string xmlData)
|
||||||
{
|
{
|
||||||
// Console.WriteLine("Input XML [{0}]", xmlData);
|
// Console.WriteLine("Input XML [{0}]", xmlData);
|
||||||
|
return ExternalRepresentationUtils.RewriteSOP(xmlData, m_scene.Name, m_HomeURI, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID);
|
||||||
|
|
||||||
using (StringWriter sw = new StringWriter())
|
|
||||||
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
|
||||||
using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
|
|
||||||
using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment }))
|
|
||||||
{
|
|
||||||
TransformXml(reader, writer);
|
|
||||||
|
|
||||||
// Console.WriteLine("Output: [{0}]", sw.ToString());
|
|
||||||
|
|
||||||
return sw.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are now taking the more complex streaming approach above because some assets can be very large
|
|
||||||
// and can trigger higher CPU use or possibly memory problems.
|
|
||||||
// XmlDocument doc = new XmlDocument();
|
|
||||||
// doc.LoadXml(xml);
|
|
||||||
// XmlNodeList sops = doc.GetElementsByTagName("SceneObjectPart");
|
|
||||||
//
|
|
||||||
// foreach (XmlNode sop in sops)
|
|
||||||
// {
|
|
||||||
// UserAccount creator = null;
|
|
||||||
// bool hasCreatorData = false;
|
|
||||||
// XmlNodeList nodes = sop.ChildNodes;
|
|
||||||
// foreach (XmlNode node in nodes)
|
|
||||||
// {
|
|
||||||
// if (node.Name == "CreatorID")
|
|
||||||
// {
|
|
||||||
// UUID uuid = UUID.Zero;
|
|
||||||
// UUID.TryParse(node.InnerText, out uuid);
|
|
||||||
// creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
|
|
||||||
// }
|
|
||||||
// if (node.Name == "CreatorData" && node.InnerText != null && node.InnerText != string.Empty)
|
|
||||||
// hasCreatorData = true;
|
|
||||||
//
|
|
||||||
// //if (node.Name == "OwnerID")
|
|
||||||
// //{
|
|
||||||
// // UserAccount owner = GetUser(node.InnerText);
|
|
||||||
// // if (owner != null)
|
|
||||||
// // node.InnerText = m_ProfileServiceURL + "/" + node.InnerText + "/" + owner.FirstName + " " + owner.LastName;
|
|
||||||
// //}
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!hasCreatorData && creator != null)
|
|
||||||
// {
|
|
||||||
// XmlElement creatorData = doc.CreateElement("CreatorData");
|
|
||||||
// creatorData.InnerText = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName;
|
|
||||||
// sop.AppendChild(creatorData);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// using (StringWriter wr = new StringWriter())
|
|
||||||
// {
|
|
||||||
// doc.Save(wr);
|
|
||||||
// return wr.ToString();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: unused
|
// TODO: unused
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
|
||||||
{
|
{
|
||||||
InventoryFolderImpl folder = null;
|
InventoryFolderImpl folder = null;
|
||||||
InventoryCollection inv = new InventoryCollection();
|
InventoryCollection inv = new InventoryCollection();
|
||||||
inv.UserID = m_Library.Owner;
|
inv.OwnerID = m_Library.Owner;
|
||||||
|
|
||||||
if (folderID != m_Library.ID)
|
if (folderID != m_Library.ID)
|
||||||
{
|
{
|
||||||
|
@ -87,6 +87,34 @@ namespace OpenSim.Region.CoreModules.Framework.Library
|
||||||
return inv;
|
return inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
|
||||||
|
{
|
||||||
|
InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
|
||||||
|
int i = 0;
|
||||||
|
foreach (UUID fid in folderIDs)
|
||||||
|
{
|
||||||
|
invColl[i++] = GetFolderContent(principalID, fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return invColl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
|
||||||
|
{
|
||||||
|
InventoryItemBase[] itemColl = new InventoryItemBase[itemIDs.Length];
|
||||||
|
int i = 0;
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.Owner = principalID;
|
||||||
|
foreach (UUID fid in itemIDs)
|
||||||
|
{
|
||||||
|
item.ID = fid;
|
||||||
|
itemColl[i++] = GetItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemColl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a new folder to the user's inventory
|
/// Add a new folder to the user's inventory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -726,6 +726,21 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
"Show the bindings between user UUIDs and user names",
|
"Show the bindings between user UUIDs and user names",
|
||||||
String.Empty,
|
String.Empty,
|
||||||
HandleShowUsers);
|
HandleShowUsers);
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand("Users", true,
|
||||||
|
"reset user cache",
|
||||||
|
"reset user cache",
|
||||||
|
"reset user cache to allow changed settings to be applied",
|
||||||
|
String.Empty,
|
||||||
|
HandleResetUserCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleResetUserCache(string module, string[] cmd)
|
||||||
|
{
|
||||||
|
lock(m_UserCache)
|
||||||
|
{
|
||||||
|
m_UserCache.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleShowUser(string module, string[] cmd)
|
private void HandleShowUser(string module, string[] cmd)
|
||||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.Region.CoreModules", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.Region.CoreModules", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -389,6 +389,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
return connector.GetFolderContent(userID, folderID);
|
return connector.GetFolderContent(userID, folderID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs)
|
||||||
|
{
|
||||||
|
string invURL = GetInventoryServiceURL(userID);
|
||||||
|
|
||||||
|
if (invURL == null) // not there, forward to local inventory connector to resolve
|
||||||
|
lock (m_Lock)
|
||||||
|
return m_LocalGridInventoryService.GetMultipleFoldersContent(userID, folderIDs);
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InventoryCollection[] coll = new InventoryCollection[folderIDs.Length];
|
||||||
|
int i = 0;
|
||||||
|
foreach (UUID fid in folderIDs)
|
||||||
|
coll[i++] = GetFolderContent(userID, fid);
|
||||||
|
|
||||||
|
return coll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
||||||
{
|
{
|
||||||
//m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID);
|
//m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID);
|
||||||
|
@ -596,6 +615,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
return connector.GetItem(item);
|
return connector.GetItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
|
||||||
|
{
|
||||||
|
if (itemIDs == null)
|
||||||
|
return new InventoryItemBase[0];
|
||||||
|
//m_log.Debug("[HG INVENTORY CONNECTOR]: GetItem " + item.ID);
|
||||||
|
|
||||||
|
string invURL = GetInventoryServiceURL(userID);
|
||||||
|
|
||||||
|
if (invURL == null) // not there, forward to local inventory connector to resolve
|
||||||
|
lock (m_Lock)
|
||||||
|
return m_LocalGridInventoryService.GetMultipleItems(userID, itemIDs);
|
||||||
|
|
||||||
|
IInventoryService connector = GetConnector(invURL);
|
||||||
|
|
||||||
|
return connector.GetMultipleItems(userID, itemIDs);
|
||||||
|
}
|
||||||
|
|
||||||
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
||||||
{
|
{
|
||||||
if (folder == null)
|
if (folder == null)
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
if (m_Inventories.TryGetValue(userID, out inv))
|
if (m_Inventories.TryGetValue(userID, out inv))
|
||||||
{
|
{
|
||||||
c = new InventoryCollection();
|
c = new InventoryCollection();
|
||||||
c.UserID = userID;
|
c.OwnerID = userID;
|
||||||
|
|
||||||
c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f)
|
c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -195,6 +195,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
return invCol;
|
return invCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
|
||||||
|
{
|
||||||
|
InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
|
||||||
|
int i = 0;
|
||||||
|
foreach (UUID fid in folderIDs)
|
||||||
|
{
|
||||||
|
invColl[i++] = GetFolderContent(principalID, fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return invColl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
||||||
{
|
{
|
||||||
return m_InventoryService.GetFolderItems(userID, folderID);
|
return m_InventoryService.GetFolderItems(userID, folderID);
|
||||||
|
@ -294,6 +307,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
|
||||||
|
{
|
||||||
|
return m_InventoryService.GetMultipleItems(userID, itemIDs);
|
||||||
|
}
|
||||||
|
|
||||||
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
||||||
{
|
{
|
||||||
return m_InventoryService.GetFolder(folder);
|
return m_InventoryService.GetFolder(folder);
|
||||||
|
|
|
@ -204,6 +204,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
return invCol;
|
return invCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
|
||||||
|
{
|
||||||
|
return m_RemoteConnector.GetMultipleFoldersContent(principalID, folderIDs);
|
||||||
|
}
|
||||||
|
|
||||||
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
||||||
{
|
{
|
||||||
return m_RemoteConnector.GetFolderItems(userID, folderID);
|
return m_RemoteConnector.GetFolderItems(userID, folderID);
|
||||||
|
@ -298,6 +303,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
||||||
return m_RemoteConnector.GetItem(item);
|
return m_RemoteConnector.GetItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
|
||||||
|
{
|
||||||
|
if (itemIDs == null)
|
||||||
|
return new InventoryItemBase[0];
|
||||||
|
|
||||||
|
return m_RemoteConnector.GetMultipleItems(userID, itemIDs);
|
||||||
|
}
|
||||||
|
|
||||||
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetFolder {0}", folder.ID);
|
//m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetFolder {0}", folder.ID);
|
||||||
|
|
|
@ -335,7 +335,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
|
if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[ARCHIVER]: Rewriting object data for {0}", asset.ID);
|
//m_log.DebugFormat("[ARCHIVER]: Rewriting object data for {0}", asset.ID);
|
||||||
string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), m_options["home"].ToString(), m_userAccountService, m_scopeID);
|
string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), string.Empty, m_options["home"].ToString(), m_userAccountService, m_scopeID);
|
||||||
asset.Data = Utils.StringToBytes(xml);
|
asset.Data = Utils.StringToBytes(xml);
|
||||||
}
|
}
|
||||||
return asset;
|
return asset;
|
||||||
|
|
|
@ -98,11 +98,17 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
// caches ExtendedLandData
|
// caches ExtendedLandData
|
||||||
private Cache parcelInfoCache;
|
private Cache parcelInfoCache;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
|
/// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>();
|
private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>();
|
||||||
|
|
||||||
|
// Enables limiting parcel layer info transmission when doing simple updates
|
||||||
|
private bool shouldLimitParcelLayerInfoToViewDistance { get; set; }
|
||||||
|
// "View distance" for sending parcel layer info if asked for from a view point in the region
|
||||||
|
private int parcelLayerViewDistance { get; set; }
|
||||||
|
|
||||||
#region INonSharedRegionModule Members
|
#region INonSharedRegionModule Members
|
||||||
|
|
||||||
public Type ReplaceableInterface
|
public Type ReplaceableInterface
|
||||||
|
@ -112,6 +118,14 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
|
|
||||||
public void Initialise(IConfigSource source)
|
public void Initialise(IConfigSource source)
|
||||||
{
|
{
|
||||||
|
shouldLimitParcelLayerInfoToViewDistance = true;
|
||||||
|
parcelLayerViewDistance = 128;
|
||||||
|
IConfig landManagementConfig = source.Configs["LandManagement"];
|
||||||
|
if (landManagementConfig != null)
|
||||||
|
{
|
||||||
|
shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance);
|
||||||
|
parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddRegion(Scene scene)
|
public void AddRegion(Scene scene)
|
||||||
|
@ -1129,11 +1143,26 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
|
|
||||||
#region Parcel Updating
|
#region Parcel Updating
|
||||||
|
|
||||||
|
// Send parcel layer info for the whole region
|
||||||
|
public void SendParcelOverlay(IClientAPI remote_client)
|
||||||
|
{
|
||||||
|
SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Where we send the ParcelOverlay packet to the client
|
/// Send the parcel overlay blocks to the client. We send the overlay packets
|
||||||
|
/// around a location and limited by the 'parcelLayerViewDistance'. This number
|
||||||
|
/// is usually 128 and the code is arranged so it sends all the parcel overlay
|
||||||
|
/// information for a whole region if the region is legacy sized (256x256). If
|
||||||
|
/// the region is larger, only the parcel layer information is sent around
|
||||||
|
/// the point specified. This reduces the problem of parcel layer information
|
||||||
|
/// blocks increasing exponentially as region size increases.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="remote_client">The object representing the client</param>
|
/// <param name="remote_client">The object representing the client</param>
|
||||||
public void SendParcelOverlay(IClientAPI remote_client)
|
/// <param name="xPlace">X position in the region to send surrounding parcel layer info</param>
|
||||||
|
/// <param name="yPlace">y position in the region to send surrounding parcel layer info</param>
|
||||||
|
/// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param>
|
||||||
|
private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance)
|
||||||
{
|
{
|
||||||
const int LAND_BLOCKS_PER_PACKET = 1024;
|
const int LAND_BLOCKS_PER_PACKET = 1024;
|
||||||
|
|
||||||
|
@ -1141,15 +1170,58 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
int byteArrayCount = 0;
|
int byteArrayCount = 0;
|
||||||
int sequenceID = 0;
|
int sequenceID = 0;
|
||||||
|
|
||||||
// Layer data is in landUnit (4m) chunks
|
int xLow = 0;
|
||||||
for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
|
int xHigh = (int)m_scene.RegionInfo.RegionSizeX;
|
||||||
|
int yLow = 0;
|
||||||
|
int yHigh = (int)m_scene.RegionInfo.RegionSizeY;
|
||||||
|
|
||||||
|
if (shouldLimitParcelLayerInfoToViewDistance)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
|
// Compute view distance around the given point
|
||||||
|
int txLow = xPlace - layerViewDistance;
|
||||||
|
int txHigh = xPlace + layerViewDistance;
|
||||||
|
// If the distance is outside the region area, move the view distance to ba all in the region
|
||||||
|
if (txLow < xLow)
|
||||||
|
{
|
||||||
|
txLow = xLow;
|
||||||
|
txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh);
|
||||||
|
}
|
||||||
|
if (txHigh > xHigh)
|
||||||
|
{
|
||||||
|
txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2));
|
||||||
|
txHigh = xHigh;
|
||||||
|
}
|
||||||
|
xLow = txLow;
|
||||||
|
xHigh = txHigh;
|
||||||
|
|
||||||
|
int tyLow = yPlace - layerViewDistance;
|
||||||
|
int tyHigh = yPlace + layerViewDistance;
|
||||||
|
if (tyLow < yLow)
|
||||||
|
{
|
||||||
|
tyLow = yLow;
|
||||||
|
tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh);
|
||||||
|
}
|
||||||
|
if (tyHigh > yHigh)
|
||||||
|
{
|
||||||
|
tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2));
|
||||||
|
tyHigh = yHigh;
|
||||||
|
}
|
||||||
|
yLow = tyLow;
|
||||||
|
yHigh = tyHigh;
|
||||||
|
}
|
||||||
|
// m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>",
|
||||||
|
// LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh);
|
||||||
|
|
||||||
|
// Layer data is in landUnit (4m) chunks
|
||||||
|
for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
|
||||||
|
{
|
||||||
|
for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
|
||||||
{
|
{
|
||||||
byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client);
|
byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client);
|
||||||
byteArrayCount++;
|
byteArrayCount++;
|
||||||
if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
|
if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length);
|
||||||
remote_client.SendLandParcelOverlay(byteArray, sequenceID);
|
remote_client.SendLandParcelOverlay(byteArray, sequenceID);
|
||||||
byteArrayCount = 0;
|
byteArrayCount = 0;
|
||||||
sequenceID++;
|
sequenceID++;
|
||||||
|
@ -1162,6 +1234,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
if (byteArrayCount != 0)
|
if (byteArrayCount != 0)
|
||||||
{
|
{
|
||||||
remote_client.SendLandParcelOverlay(byteArray, sequenceID);
|
remote_client.SendLandParcelOverlay(byteArray, sequenceID);
|
||||||
|
// m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1265,7 +1338,8 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
|
temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendParcelOverlay(remote_client);
|
// Also send the layer data around the point of interest
|
||||||
|
SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
|
public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of the OpenSimulator Project nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using OpenSim.Region.CoreModules.World.Terrain;
|
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.World.Terrain.Features
|
|
||||||
{
|
|
||||||
public class RectangleFeature : TerrainFeature
|
|
||||||
{
|
|
||||||
public RectangleFeature(ITerrainModule module) : base(module)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string CreateFeature(ITerrainChannel map, string[] args)
|
|
||||||
{
|
|
||||||
string val;
|
|
||||||
string result;
|
|
||||||
if (args.Length < 7)
|
|
||||||
{
|
|
||||||
result = "Usage: " + GetUsage();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = String.Empty;
|
|
||||||
|
|
||||||
float targetElevation;
|
|
||||||
val = base.parseFloat(args[3], out targetElevation);
|
|
||||||
if (val != String.Empty)
|
|
||||||
{
|
|
||||||
result = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
int xOrigin;
|
|
||||||
val = base.parseInt(args[4], out xOrigin);
|
|
||||||
if (val != String.Empty)
|
|
||||||
{
|
|
||||||
result = val;
|
|
||||||
}
|
|
||||||
else if (xOrigin < 0 || xOrigin >= map.Width)
|
|
||||||
{
|
|
||||||
result = "x-origin must be within the region";
|
|
||||||
}
|
|
||||||
|
|
||||||
int yOrigin;
|
|
||||||
val = base.parseInt(args[5], out yOrigin);
|
|
||||||
if (val != String.Empty)
|
|
||||||
{
|
|
||||||
result = val;
|
|
||||||
}
|
|
||||||
else if (yOrigin < 0 || yOrigin >= map.Height)
|
|
||||||
{
|
|
||||||
result = "y-origin must be within the region";
|
|
||||||
}
|
|
||||||
|
|
||||||
int xDelta;
|
|
||||||
val = base.parseInt(args[6], out xDelta);
|
|
||||||
if (val != String.Empty)
|
|
||||||
{
|
|
||||||
result = val;
|
|
||||||
}
|
|
||||||
else if (xDelta <= 0)
|
|
||||||
{
|
|
||||||
result = "x-size must be greater than zero";
|
|
||||||
}
|
|
||||||
|
|
||||||
int yDelta;
|
|
||||||
if (args.Length > 7)
|
|
||||||
{
|
|
||||||
val = base.parseInt(args[7], out yDelta);
|
|
||||||
if (val != String.Empty)
|
|
||||||
{
|
|
||||||
result = val;
|
|
||||||
}
|
|
||||||
else if (yDelta <= 0)
|
|
||||||
{
|
|
||||||
result = "y-size must be greater than zero";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no y-size.. make it square
|
|
||||||
yDelta = xDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
// slightly more complex validation, if required.
|
|
||||||
if (result == String.Empty)
|
|
||||||
{
|
|
||||||
if (xOrigin + xDelta > map.Width)
|
|
||||||
{
|
|
||||||
result = "(x-origin + x-size) must be within the region size";
|
|
||||||
}
|
|
||||||
else if (yOrigin + yDelta > map.Height)
|
|
||||||
{
|
|
||||||
result = "(y-origin + y-size) must be within the region size";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it's all good, then do the work
|
|
||||||
if (result == String.Empty)
|
|
||||||
{
|
|
||||||
int yPos = yOrigin + yDelta;
|
|
||||||
while(--yPos >= yOrigin)
|
|
||||||
{
|
|
||||||
int xPos = xOrigin + xDelta;
|
|
||||||
while(--xPos >= xOrigin)
|
|
||||||
{
|
|
||||||
map[xPos, yPos] = (double)targetElevation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetUsage()
|
|
||||||
{
|
|
||||||
return "rectangle <height> <x-origin> <y-origin> <x-size> [<y-size>]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,65 +24,53 @@
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
|
using System;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.World.Terrain
|
namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
{
|
{
|
||||||
public abstract class TerrainFeature : ITerrainFeature
|
public interface ITerrainModifier
|
||||||
{
|
{
|
||||||
protected ITerrainModule m_module;
|
/// <summary>
|
||||||
|
/// Creates the feature.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Empty string if successful, otherwise error message.
|
||||||
|
/// </returns>
|
||||||
|
/// <param name='map'>
|
||||||
|
/// ITerrainChannel holding terrain data.
|
||||||
|
/// </param>
|
||||||
|
/// <param name='args'>
|
||||||
|
/// command-line arguments from console.
|
||||||
|
/// </param>
|
||||||
|
string ModifyTerrain(ITerrainChannel map, string[] args);
|
||||||
|
|
||||||
protected TerrainFeature(ITerrainModule module)
|
/// <summary>
|
||||||
{
|
/// Gets a string describing the usage.
|
||||||
m_module = module;
|
/// </summary>
|
||||||
}
|
/// <returns>
|
||||||
|
/// A string describing parameters for creating the feature.
|
||||||
public abstract string CreateFeature(ITerrainChannel map, string[] args);
|
/// Format is "feature-name <arg1> <arg2> ..."
|
||||||
|
/// </returns>
|
||||||
public abstract string GetUsage();
|
string GetUsage();
|
||||||
|
|
||||||
protected string parseFloat(String s, out float f)
|
|
||||||
{
|
|
||||||
string result;
|
|
||||||
double d;
|
|
||||||
if (Double.TryParse(s, out d))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
f = (float)d;
|
|
||||||
result = String.Empty;
|
|
||||||
}
|
|
||||||
catch(InvalidCastException)
|
|
||||||
{
|
|
||||||
result = String.Format("{0} is invalid", s);
|
|
||||||
f = -1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f = -1.0f;
|
|
||||||
result = String.Format("{0} is invalid", s);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected string parseInt(String s, out int i)
|
|
||||||
{
|
|
||||||
string result;
|
|
||||||
if (Int32.TryParse(s, out i))
|
|
||||||
{
|
|
||||||
result = String.Empty;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = String.Format("{0} is invalid", s);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply the appropriate operation on the specified map, at (x, y).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='map'>
|
||||||
|
/// Map.
|
||||||
|
/// </param>
|
||||||
|
/// <param name='data'>
|
||||||
|
/// Data.
|
||||||
|
/// </param>
|
||||||
|
/// <param name='x'>
|
||||||
|
/// X.
|
||||||
|
/// </param>
|
||||||
|
/// <param name='y'>
|
||||||
|
/// Y.
|
||||||
|
/// </param>
|
||||||
|
double operate(double[,] map, TerrainModifierData data, int x, int y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using OpenSim.Region.CoreModules.World.Terrain;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
|
||||||
|
{
|
||||||
|
public class FillModifier : TerrainModifier
|
||||||
|
{
|
||||||
|
|
||||||
|
public FillModifier(ITerrainModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModifyTerrain(ITerrainChannel map, string[] args)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (args.Length < 3)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TerrainModifierData data;
|
||||||
|
result = this.parseParameters(args, out data);
|
||||||
|
|
||||||
|
// Context-specific validation
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (data.shape == String.Empty)
|
||||||
|
{
|
||||||
|
data.shape = "rectangle";
|
||||||
|
data.x0 = 0;
|
||||||
|
data.y0 = 0;
|
||||||
|
data.dx = map.Width;
|
||||||
|
data.dy = map.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's all good, then do the work
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
this.applyModification(map, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetUsage()
|
||||||
|
{
|
||||||
|
string val = "fill <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
|
||||||
|
+ "\nSets all points within the specified range to the specified value.";
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double operate(double[,] map, TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
double factor = this.computeBevel(data, x, y);
|
||||||
|
double result = data.elevation - (data.elevation - data.bevelevation) * factor;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.CoreModules.World.Terrain;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
|
||||||
|
{
|
||||||
|
public class LowerModifier : TerrainModifier
|
||||||
|
{
|
||||||
|
public LowerModifier(ITerrainModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModifyTerrain(ITerrainChannel map, string[] args)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (args.Length < 3)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TerrainModifierData data;
|
||||||
|
result = this.parseParameters(args, out data);
|
||||||
|
|
||||||
|
// Context-specific validation
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (data.shape == String.Empty)
|
||||||
|
{
|
||||||
|
data.shape = "rectangle";
|
||||||
|
data.x0 = 0;
|
||||||
|
data.y0 = 0;
|
||||||
|
data.dx = map.Width;
|
||||||
|
data.dy = map.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's all good, then do the work
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
this.applyModification(map, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetUsage()
|
||||||
|
{
|
||||||
|
string val = "lower <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
|
||||||
|
+ "\nLowers all points within the specified range by the specified amount.";
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double operate(double[,] map, TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
double factor = this.computeBevel(data, x, y);
|
||||||
|
double result = map[x, y] - (data.elevation - (data.elevation - data.bevelevation) * factor);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.CoreModules.World.Terrain;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
|
||||||
|
{
|
||||||
|
public class MaxModifier : TerrainModifier
|
||||||
|
{
|
||||||
|
public MaxModifier(ITerrainModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModifyTerrain(ITerrainChannel map, string[] args)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (args.Length < 3)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TerrainModifierData data;
|
||||||
|
result = this.parseParameters(args, out data);
|
||||||
|
|
||||||
|
// Context-specific validation
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (data.shape == String.Empty)
|
||||||
|
{
|
||||||
|
data.shape = "rectangle";
|
||||||
|
data.x0 = 0;
|
||||||
|
data.y0 = 0;
|
||||||
|
data.dx = map.Width;
|
||||||
|
data.dy = map.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's all good, then do the work
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
this.applyModification(map, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetUsage()
|
||||||
|
{
|
||||||
|
string val = "max <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
|
||||||
|
+ "\nEnsures that all points within the specified range are no higher than the specified value.";
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double operate(double[,] map, TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
double factor = this.computeBevel(data, x, y);
|
||||||
|
double result = Math.Min(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.CoreModules.World.Terrain;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
|
||||||
|
{
|
||||||
|
public class MinModifier : TerrainModifier
|
||||||
|
{
|
||||||
|
public MinModifier(ITerrainModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModifyTerrain(ITerrainChannel map, string[] args)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (args.Length < 3)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TerrainModifierData data;
|
||||||
|
result = this.parseParameters(args, out data);
|
||||||
|
|
||||||
|
// Context-specific validation
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (data.shape == String.Empty)
|
||||||
|
{
|
||||||
|
data.shape = "rectangle";
|
||||||
|
data.x0 = 0;
|
||||||
|
data.y0 = 0;
|
||||||
|
data.dx = map.Width;
|
||||||
|
data.dy = map.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's all good, then do the work
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
this.applyModification(map, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetUsage()
|
||||||
|
{
|
||||||
|
string val = "min <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
|
||||||
|
+ "\nEnsures that all points within the specified range are no lower than the specified value.";
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double operate(double[,] map, TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
double factor = this.computeBevel(data, x, y);
|
||||||
|
double result = Math.Max(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.CoreModules.World.Terrain;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
|
||||||
|
{
|
||||||
|
public class NoiseModifier : TerrainModifier
|
||||||
|
{
|
||||||
|
public NoiseModifier(ITerrainModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModifyTerrain(ITerrainChannel map, string[] args)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (args.Length < 3)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TerrainModifierData data;
|
||||||
|
result = this.parseParameters(args, out data);
|
||||||
|
|
||||||
|
// Context-specific validation
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (data.bevel == "taper")
|
||||||
|
{
|
||||||
|
if (data.bevelevation < 0.0 || data.bevelevation > 1.0)
|
||||||
|
{
|
||||||
|
result = String.Format("Taper must be 0.0 to 1.0: {0}", data.bevelevation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.bevelevation = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.elevation < 0.0 || data.elevation > 1.0)
|
||||||
|
{
|
||||||
|
result = String.Format("Noise strength must be 0.0 to 1.0: {0}", data.elevation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.shape == String.Empty)
|
||||||
|
{
|
||||||
|
data.shape = "rectangle";
|
||||||
|
data.x0 = 0;
|
||||||
|
data.y0 = 0;
|
||||||
|
data.dx = map.Width;
|
||||||
|
data.dy = map.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's all good, then do the work
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
this.applyModification(map, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetUsage()
|
||||||
|
{
|
||||||
|
string val = "noise <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
|
||||||
|
+ "\nAdds noise to all points within the specified range.";
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double operate(double[,] map, TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
double factor = this.computeBevel(data, x, y);
|
||||||
|
double noise = TerrainUtil.PerlinNoise2D((double)x / map.GetLength(0), (double)y / map.GetLength(1), 8, 1.0);
|
||||||
|
return map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor) * (noise - .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.CoreModules.World.Terrain;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
|
||||||
|
{
|
||||||
|
public class RaiseModifier : TerrainModifier
|
||||||
|
{
|
||||||
|
public RaiseModifier(ITerrainModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModifyTerrain(ITerrainChannel map, string[] args)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (args.Length < 3)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TerrainModifierData data;
|
||||||
|
result = this.parseParameters(args, out data);
|
||||||
|
|
||||||
|
// Context-specific validation
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (data.shape == String.Empty)
|
||||||
|
{
|
||||||
|
data.shape = "rectangle";
|
||||||
|
data.x0 = 0;
|
||||||
|
data.y0 = 0;
|
||||||
|
data.dx = map.Width;
|
||||||
|
data.dy = map.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's all good, then do the work
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
this.applyModification(map, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetUsage()
|
||||||
|
{
|
||||||
|
string val = "raise <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
|
||||||
|
+ "\nRaises all points within the specified range by the specified amount.";
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double operate(double[,] map, TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
double factor = this.computeBevel(data, x, y);
|
||||||
|
double result = map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.CoreModules.World.Terrain;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
|
||||||
|
{
|
||||||
|
public class SmoothModifier : TerrainModifier
|
||||||
|
{
|
||||||
|
public SmoothModifier(ITerrainModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ModifyTerrain(ITerrainChannel map, string[] args)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (args.Length < 3)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TerrainModifierData data;
|
||||||
|
result = this.parseParameters(args, out data);
|
||||||
|
|
||||||
|
// Context-specific validation
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (data.bevel == "taper")
|
||||||
|
{
|
||||||
|
if (data.bevelevation < 0.01 || data.bevelevation > 0.99)
|
||||||
|
{
|
||||||
|
result = String.Format("Taper must be 0.01 to 0.99: {0}", data.bevelevation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.bevelevation = 2.0f / 3.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.elevation < 0.0 || data.elevation > 1.0)
|
||||||
|
{
|
||||||
|
result = String.Format("Smoothing strength must be 0.0 to 1.0: {0}", data.elevation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.shape == String.Empty)
|
||||||
|
{
|
||||||
|
data.shape = "rectangle";
|
||||||
|
data.x0 = 0;
|
||||||
|
data.y0 = 0;
|
||||||
|
data.dx = map.Width;
|
||||||
|
data.dy = map.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's all good, then do the work
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
this.applyModification(map, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetUsage()
|
||||||
|
{
|
||||||
|
string val = "smooth <strength> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<fraction>]"
|
||||||
|
+ "\nSmooths all points within the specified range using a simple averaging algorithm.";
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override double operate(double[,] map, TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
double[] scale = new double[3];
|
||||||
|
scale[0] = data.elevation;
|
||||||
|
scale[1] = ((1.0 - scale[0]) * data.bevelevation) / 8.0;
|
||||||
|
scale[2] = ((1.0 - scale[0]) * (1.0 - data.bevelevation)) / 16.0;
|
||||||
|
int xMax = map.GetLength(0);
|
||||||
|
int yMax = map.GetLength(1);
|
||||||
|
double result;
|
||||||
|
if ((x == 0) || (y == 0) || (x == (xMax - 1)) || (y == (yMax - 1)))
|
||||||
|
{
|
||||||
|
result = map[x, y];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = 0.0;
|
||||||
|
for(int yPos = (y - 2); yPos < (y + 3); yPos++)
|
||||||
|
{
|
||||||
|
int yVal = (yPos <= 0) ? 0 : ((yPos < yMax) ? yPos : yMax - 1);
|
||||||
|
for(int xPos = (x - 2); xPos < (x + 3); xPos++)
|
||||||
|
{
|
||||||
|
int xVal = (xPos <= 0) ? 0 : ((xPos < xMax) ? xPos : xMax - 1);
|
||||||
|
int dist = Math.Max(Math.Abs(x - xVal), Math.Abs(y - yVal));
|
||||||
|
result += map[xVal, yVal] * scale[dist];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,378 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
|
{
|
||||||
|
public abstract class TerrainModifier : ITerrainModifier
|
||||||
|
{
|
||||||
|
protected ITerrainModule m_module;
|
||||||
|
protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
protected TerrainModifier(ITerrainModule module)
|
||||||
|
{
|
||||||
|
m_module = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract string ModifyTerrain(ITerrainChannel map, string[] args);
|
||||||
|
|
||||||
|
public abstract string GetUsage();
|
||||||
|
|
||||||
|
public abstract double operate(double[,] map, TerrainModifierData data, int x, int y);
|
||||||
|
|
||||||
|
protected String parseParameters(string[] args, out TerrainModifierData data)
|
||||||
|
{
|
||||||
|
string val;
|
||||||
|
string arg;
|
||||||
|
string result;
|
||||||
|
data = new TerrainModifierData();
|
||||||
|
data.shape = String.Empty;
|
||||||
|
data.bevel = String.Empty;
|
||||||
|
data.dx = 0;
|
||||||
|
data.dy = 0;
|
||||||
|
if (args.Length < 4)
|
||||||
|
{
|
||||||
|
result = "Usage: " + GetUsage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = this.parseFloat(args[3], out data.elevation);
|
||||||
|
}
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
int index = 3;
|
||||||
|
while(++index < args.Length && result == String.Empty)
|
||||||
|
{
|
||||||
|
arg = args[index];
|
||||||
|
// check for shape
|
||||||
|
if (arg.StartsWith("-rec=") || arg.StartsWith("-ell="))
|
||||||
|
{
|
||||||
|
if (data.shape != String.Empty)
|
||||||
|
{
|
||||||
|
result = "Only 1 '-rec' or '-ell' parameter is permitted.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.shape = arg.StartsWith("-ell=") ? "ellipse" : "rectangle";
|
||||||
|
val = arg.Substring(arg.IndexOf("=") + 1);
|
||||||
|
string[] coords = val.Split(new char[] {','});
|
||||||
|
if ((coords.Length < 3) || (coords.Length > 4))
|
||||||
|
{
|
||||||
|
result = String.Format("Bad format for shape parameter {0}", arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = this.parseInt(coords[0], out data.x0);
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
result = this.parseInt(coords[1], out data.y0);
|
||||||
|
}
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
result = this.parseInt(coords[2], out data.dx);
|
||||||
|
}
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if (coords.Length == 4)
|
||||||
|
{
|
||||||
|
result = this.parseInt(coords[3], out data.dy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.dy = data.dx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == String.Empty)
|
||||||
|
{
|
||||||
|
if ((data.dx <= 0) || (data.dy <= 0))
|
||||||
|
{
|
||||||
|
result = "Shape sizes must be positive integers";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = String.Format("Bad value in shape parameters {0}", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arg.StartsWith("-taper="))
|
||||||
|
{
|
||||||
|
if (data.bevel != String.Empty)
|
||||||
|
{
|
||||||
|
result = "Only 1 '-taper' parameter is permitted.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.bevel = "taper";
|
||||||
|
val = arg.Substring(arg.IndexOf("=") + 1);
|
||||||
|
result = this.parseFloat(val, out data.bevelevation);
|
||||||
|
if (result != String.Empty)
|
||||||
|
{
|
||||||
|
result = String.Format("Bad format for taper parameter {0}", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = String.Format("Unrecognized parameter {0}", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string parseFloat(String s, out float f)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
double d;
|
||||||
|
if (Double.TryParse(s, out d))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
f = (float)d;
|
||||||
|
result = String.Empty;
|
||||||
|
}
|
||||||
|
catch(InvalidCastException)
|
||||||
|
{
|
||||||
|
result = String.Format("{0} is invalid", s);
|
||||||
|
f = -1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f = -1.0f;
|
||||||
|
result = String.Format("{0} is invalid", s);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string parseInt(String s, out int i)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (Int32.TryParse(s, out i))
|
||||||
|
{
|
||||||
|
result = String.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = String.Format("{0} is invalid", s);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void applyModification(ITerrainChannel map, TerrainModifierData data)
|
||||||
|
{
|
||||||
|
bool[,] mask;
|
||||||
|
int xMax;
|
||||||
|
int yMax;
|
||||||
|
int xMid;
|
||||||
|
int yMid;
|
||||||
|
if (data.shape == "ellipse")
|
||||||
|
{
|
||||||
|
mask = this.ellipticalMask(data.dx, data.dy);
|
||||||
|
xMax = mask.GetLength(0);
|
||||||
|
yMax = mask.GetLength(1);
|
||||||
|
xMid = xMax / 2 + xMax % 2;
|
||||||
|
yMid = yMax / 2 + yMax % 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = this.rectangularMask(data.dx, data.dy);
|
||||||
|
xMax = mask.GetLength(0);
|
||||||
|
yMax = mask.GetLength(1);
|
||||||
|
xMid = 0;
|
||||||
|
yMid = 0;
|
||||||
|
}
|
||||||
|
// m_log.DebugFormat("Apply {0} mask {1}x{2} @ {3},{4}", data.shape, xMax, yMax, xMid, yMid);
|
||||||
|
double[,] buffer = map.GetDoubles();
|
||||||
|
int yDim = yMax;
|
||||||
|
while(--yDim >= 0)
|
||||||
|
{
|
||||||
|
int yPos = data.y0 + yDim - yMid;
|
||||||
|
if ((yPos >= 0) && (yPos < map.Height))
|
||||||
|
{
|
||||||
|
int xDim = xMax;
|
||||||
|
while(--xDim >= 0)
|
||||||
|
{
|
||||||
|
int xPos = data.x0 + xDim - xMid;
|
||||||
|
if ((xPos >= 0) && (xPos < map.Width) && (mask[xDim, yDim]))
|
||||||
|
{
|
||||||
|
double endElevation = this.operate(buffer, data, xPos, yPos);
|
||||||
|
map[xPos, yPos] = endElevation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected double computeBevel(TerrainModifierData data, int x, int y)
|
||||||
|
{
|
||||||
|
int deltaX;
|
||||||
|
int deltaY;
|
||||||
|
int xMax;
|
||||||
|
int yMax;
|
||||||
|
double factor;
|
||||||
|
if (data.bevel == "taper")
|
||||||
|
{
|
||||||
|
if (data.shape == "ellipse")
|
||||||
|
{
|
||||||
|
deltaX = x - data.x0;
|
||||||
|
deltaY = y - data.y0;
|
||||||
|
xMax = data.dx;
|
||||||
|
yMax = data.dy;
|
||||||
|
factor = (double)((deltaX * deltaX) + (deltaY * deltaY));
|
||||||
|
factor /= ((xMax * xMax) + (yMax * yMax));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pyramid
|
||||||
|
xMax = data.dx / 2 + data.dx % 2;
|
||||||
|
yMax = data.dy / 2 + data.dy % 2;
|
||||||
|
deltaX = Math.Abs(data.x0 + xMax - x);
|
||||||
|
deltaY = Math.Abs(data.y0 + yMax - y);
|
||||||
|
factor = Math.Max(((double)(deltaY) / yMax), ((double)(deltaX) / xMax));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
factor = 0.0;
|
||||||
|
}
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool[,] rectangularMask(int xSize, int ySize)
|
||||||
|
{
|
||||||
|
bool[,] mask = new bool[xSize, ySize];
|
||||||
|
int yPos = ySize;
|
||||||
|
while(--yPos >= 0)
|
||||||
|
{
|
||||||
|
int xPos = xSize;
|
||||||
|
while(--xPos >= 0)
|
||||||
|
{
|
||||||
|
mask[xPos, yPos] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fast ellipse-based derivative of Bresenham algorithm.
|
||||||
|
* https://web.archive.org/web/20120225095359/http://homepage.smc.edu/kennedy_john/belipse.pdf
|
||||||
|
*/
|
||||||
|
private bool[,] ellipticalMask(int xRadius, int yRadius)
|
||||||
|
{
|
||||||
|
long twoASquared = 2L * xRadius * xRadius;
|
||||||
|
long twoBSquared = 2L * yRadius * yRadius;
|
||||||
|
|
||||||
|
bool[,] mask = new bool[2 * xRadius + 1, 2 * yRadius + 1];
|
||||||
|
|
||||||
|
long ellipseError = 0L;
|
||||||
|
long stoppingX = twoBSquared * xRadius;
|
||||||
|
long stoppingY = 0L;
|
||||||
|
long xChange = yRadius * yRadius * (1L - 2L * xRadius);
|
||||||
|
long yChange = xRadius * xRadius;
|
||||||
|
|
||||||
|
int xPos = xRadius;
|
||||||
|
int yPos = 0;
|
||||||
|
|
||||||
|
// first set of points
|
||||||
|
while(stoppingX >= stoppingY)
|
||||||
|
{
|
||||||
|
int yUpper = yRadius + yPos;
|
||||||
|
int yLower = yRadius - yPos;
|
||||||
|
// fill in the mask
|
||||||
|
int xNow = xPos;
|
||||||
|
while(xNow >= 0)
|
||||||
|
{
|
||||||
|
mask[xRadius + xNow, yUpper] = true;
|
||||||
|
mask[xRadius - xNow, yUpper] = true;
|
||||||
|
mask[xRadius + xNow, yLower] = true;
|
||||||
|
mask[xRadius - xNow, yLower] = true;
|
||||||
|
--xNow;
|
||||||
|
}
|
||||||
|
yPos++;
|
||||||
|
stoppingY += twoASquared;
|
||||||
|
ellipseError += yChange;
|
||||||
|
yChange += twoASquared;
|
||||||
|
if ((2L * ellipseError + xChange) > 0L)
|
||||||
|
{
|
||||||
|
xPos--;
|
||||||
|
stoppingX -= twoBSquared;
|
||||||
|
ellipseError += xChange;
|
||||||
|
xChange += twoBSquared;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// second set of points
|
||||||
|
xPos = 0;
|
||||||
|
yPos = yRadius;
|
||||||
|
xChange = yRadius * yRadius;
|
||||||
|
yChange = xRadius * xRadius * (1L - 2L * yRadius);
|
||||||
|
|
||||||
|
ellipseError = 0L;
|
||||||
|
stoppingX = 0L;
|
||||||
|
stoppingY = twoASquared * yRadius;
|
||||||
|
|
||||||
|
while(stoppingX <= stoppingY)
|
||||||
|
{
|
||||||
|
int xUpper = xRadius + xPos;
|
||||||
|
int xLower = xRadius - xPos;
|
||||||
|
// fill in the mask
|
||||||
|
int yNow = yPos;
|
||||||
|
while(yNow >= 0)
|
||||||
|
{
|
||||||
|
mask[xUpper, yRadius + yNow] = true;
|
||||||
|
mask[xUpper, yRadius - yNow] = true;
|
||||||
|
mask[xLower, yRadius + yNow] = true;
|
||||||
|
mask[xLower, yRadius - yNow] = true;
|
||||||
|
--yNow;
|
||||||
|
}
|
||||||
|
xPos++;
|
||||||
|
stoppingX += twoBSquared;
|
||||||
|
ellipseError += xChange;
|
||||||
|
xChange += twoBSquared;
|
||||||
|
if ((2L * ellipseError + yChange) > 0L)
|
||||||
|
{
|
||||||
|
yPos--;
|
||||||
|
stoppingY -= twoASquared;
|
||||||
|
ellipseError += yChange;
|
||||||
|
yChange += twoASquared;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
|
{
|
||||||
|
public struct TerrainModifierData
|
||||||
|
{
|
||||||
|
public float elevation;
|
||||||
|
public string shape;
|
||||||
|
public int x0;
|
||||||
|
public int y0;
|
||||||
|
public int dx;
|
||||||
|
public int dy;
|
||||||
|
public string bevel;
|
||||||
|
public float bevelevation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -42,7 +41,7 @@ using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||||
using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
|
using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
|
||||||
using OpenSim.Region.CoreModules.World.Terrain.Features;
|
using OpenSim.Region.CoreModules.World.Terrain.Modifiers;
|
||||||
using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes;
|
using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes;
|
||||||
using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
|
using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
@ -75,14 +74,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Terrain Features
|
|
||||||
/// </summary>
|
|
||||||
public enum TerrainFeatures: byte
|
|
||||||
{
|
|
||||||
Rectangle = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
#pragma warning disable 414
|
#pragma warning disable 414
|
||||||
|
@ -90,26 +81,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
#pragma warning restore 414
|
#pragma warning restore 414
|
||||||
|
|
||||||
private readonly Commander m_commander = new Commander("terrain");
|
private readonly Commander m_commander = new Commander("terrain");
|
||||||
|
|
||||||
private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
|
private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
|
||||||
new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
|
new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
|
||||||
|
|
||||||
private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
|
private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
|
||||||
|
|
||||||
private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
|
private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
|
||||||
new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
|
new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
|
||||||
|
|
||||||
private Dictionary<string, ITerrainEffect> m_plugineffects;
|
private Dictionary<string, ITerrainEffect> m_plugineffects;
|
||||||
|
private Dictionary<string, ITerrainModifier> m_modifyOperations =
|
||||||
private Dictionary<string, ITerrainFeature> m_featureEffects =
|
new Dictionary<string, ITerrainModifier>();
|
||||||
new Dictionary<string, ITerrainFeature>();
|
|
||||||
|
|
||||||
private ITerrainChannel m_channel;
|
private ITerrainChannel m_channel;
|
||||||
private ITerrainChannel m_revert;
|
private ITerrainChannel m_revert;
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private volatile bool m_tainted;
|
private volatile bool m_tainted;
|
||||||
private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5);
|
private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5);
|
||||||
|
|
||||||
private String m_InitialTerrain = "pinhead-island";
|
private String m_InitialTerrain = "pinhead-island";
|
||||||
|
|
||||||
// If true, send terrain patch updates to clients based on their view distance
|
// If true, send terrain patch updates to clients based on their view distance
|
||||||
|
@ -136,14 +120,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
{
|
{
|
||||||
return (updateCount > 0);
|
return (updateCount > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetByXY(int x, int y, bool state)
|
public void SetByXY(int x, int y, bool state)
|
||||||
{
|
{
|
||||||
this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
|
this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetByPatch(int patchX, int patchY)
|
public bool GetByPatch(int patchX, int patchY)
|
||||||
{
|
{
|
||||||
return updated[patchX, patchY];
|
return updated[patchX, patchY];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetByPatch(int patchX, int patchY, bool state)
|
public void SetByPatch(int patchX, int patchY, bool state)
|
||||||
{
|
{
|
||||||
bool prevState = updated[patchX, patchY];
|
bool prevState = updated[patchX, patchY];
|
||||||
|
@ -153,6 +140,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
updateCount--;
|
updateCount--;
|
||||||
updated[patchX, patchY] = state;
|
updated[patchX, patchY] = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAll(bool state)
|
public void SetAll(bool state)
|
||||||
{
|
{
|
||||||
updateCount = 0;
|
updateCount = 0;
|
||||||
|
@ -201,8 +189,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
|
|
||||||
#region ICommandableModule Members
|
#region ICommandableModule Members
|
||||||
|
|
||||||
public ICommander CommandInterface
|
public ICommander CommandInterface {
|
||||||
{
|
|
||||||
get { return m_commander; }
|
get { return m_commander; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,13 +291,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type ReplaceableInterface
|
public Type ReplaceableInterface {
|
||||||
{
|
|
||||||
get { return null; }
|
get { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name {
|
||||||
{
|
|
||||||
get { return "TerrainModule"; }
|
get { return "TerrainModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,8 +646,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
|
m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
|
||||||
m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert);
|
m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert);
|
||||||
|
|
||||||
// Terrain Feature effects
|
// Terrain Modifier operations
|
||||||
m_featureEffects["rectangle"] = new RectangleFeature(this);
|
m_modifyOperations["min"] = new MinModifier(this);
|
||||||
|
m_modifyOperations["max"] = new MaxModifier(this);
|
||||||
|
m_modifyOperations["raise"] = new RaiseModifier(this);
|
||||||
|
m_modifyOperations["lower"] = new LowerModifier(this);
|
||||||
|
m_modifyOperations["fill"] = new FillModifier(this);
|
||||||
|
m_modifyOperations["smooth"] = new SmoothModifier(this);
|
||||||
|
m_modifyOperations["noise"] = new NoiseModifier(this);
|
||||||
|
|
||||||
// Filesystem load/save loaders
|
// Filesystem load/save loaders
|
||||||
m_loaders[".r32"] = new RAW32();
|
m_loaders[".r32"] = new RAW32();
|
||||||
|
@ -1019,12 +1010,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
public int PatchX;
|
public int PatchX;
|
||||||
public int PatchY;
|
public int PatchY;
|
||||||
public float Dist;
|
public float Dist;
|
||||||
|
|
||||||
public PatchesToSend(int pX, int pY, float pDist)
|
public PatchesToSend(int pX, int pY, float pDist)
|
||||||
{
|
{
|
||||||
PatchX = pX;
|
PatchX = pX;
|
||||||
PatchY = pY;
|
PatchY = pY;
|
||||||
Dist = pDist;
|
Dist = pDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CompareTo(PatchesToSend other)
|
public int CompareTo(PatchesToSend other)
|
||||||
{
|
{
|
||||||
return Dist.CompareTo(other.Dist);
|
return Dist.CompareTo(other.Dist);
|
||||||
|
@ -1665,45 +1658,64 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||||
// Add this to our scene so scripts can call these functions
|
// Add this to our scene so scripts can call these functions
|
||||||
m_scene.RegisterModuleCommander(m_commander);
|
m_scene.RegisterModuleCommander(m_commander);
|
||||||
|
|
||||||
// Add Feature command to Scene, since Command object requires fixed-length arglists
|
// Add Modify command to Scene, since Command object requires fixed-length arglists
|
||||||
m_scene.AddCommand("Terrain", this, "terrain feature",
|
m_scene.AddCommand("Terrain", this, "terrain modify",
|
||||||
"terrain feature <type> <parameters...>", "Constructs a feature of the requested type.", FeatureCommand);
|
"terrain modify <operation> <value> [<area>] [<taper>]",
|
||||||
|
"Modifies the terrain as instructed." +
|
||||||
|
"\nEach operation can be limited to an area of effect:" +
|
||||||
|
"\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" +
|
||||||
|
"\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" +
|
||||||
|
"\nEach operation can have its effect tapered based on distance from centre:" +
|
||||||
|
"\n * elliptical operations taper as cones" +
|
||||||
|
"\n * rectangular operations taper as pyramids"
|
||||||
|
,
|
||||||
|
ModifyCommand);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FeatureCommand(string module, string[] cmd)
|
public void ModifyCommand(string module, string[] cmd)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
if (cmd.Length > 2)
|
Scene scene = SceneManager.Instance.CurrentScene;
|
||||||
|
if ((scene != null) && (scene != m_scene))
|
||||||
{
|
{
|
||||||
string featureType = cmd[2];
|
result = String.Empty;
|
||||||
|
}
|
||||||
|
else if (cmd.Length > 2)
|
||||||
|
{
|
||||||
|
string operationType = cmd[2];
|
||||||
|
|
||||||
ITerrainFeature feature;
|
|
||||||
if (!m_featureEffects.TryGetValue(featureType, out feature))
|
ITerrainModifier operation;
|
||||||
|
if (!m_modifyOperations.TryGetValue(operationType, out operation))
|
||||||
{
|
{
|
||||||
result = String.Format("Terrain Feature \"{0}\" not found.", featureType);
|
result = String.Format("Terrain Modify \"{0}\" not found.", operationType);
|
||||||
}
|
}
|
||||||
else if ((cmd.Length > 3) && (cmd[3] == "usage"))
|
else if ((cmd.Length > 3) && (cmd[3] == "usage"))
|
||||||
{
|
{
|
||||||
result = "Usage: " + feature.GetUsage();
|
result = "Usage: " + operation.GetUsage();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = feature.CreateFeature(m_channel, cmd);
|
result = operation.ModifyTerrain(m_channel, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == String.Empty)
|
if (result == String.Empty)
|
||||||
{
|
{
|
||||||
result = "Created Feature";
|
result = "Modified terrain";
|
||||||
m_log.DebugFormat("Created terrain feature {0}", featureType);
|
m_log.DebugFormat("Performed terrain operation {0}", operationType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = "Usage: <feature-name> <arg1> <arg2>...";
|
result = "Usage: <operation-name> <arg1> <arg2>...";
|
||||||
}
|
}
|
||||||
|
if (result != String.Empty)
|
||||||
|
{
|
||||||
MainConsole.Instance.Output(result);
|
MainConsole.Instance.Output(result);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,6 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
[assembly: AddinRoot("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinRoot("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
||||||
|
|
|
@ -1653,7 +1653,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// These variables will be used to save the precise frame time using the
|
// These variables will be used to save the precise frame time using the
|
||||||
// Stopwatch class of Microsoft SDK; the times are recorded at the start
|
// Stopwatch class of Microsoft SDK; the times are recorded at the start
|
||||||
// and end of a parcticular section of code, and then used to calculate
|
// and end of a particular section of code, and then used to calculate
|
||||||
// the frame times, which are the sums of the sections for each given name
|
// the frame times, which are the sums of the sections for each given name
|
||||||
double preciseTotalFrameTime = 0.0;
|
double preciseTotalFrameTime = 0.0;
|
||||||
double preciseSimFrameTime = 0.0;
|
double preciseSimFrameTime = 0.0;
|
||||||
|
|
|
@ -2672,20 +2672,27 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//NonPhysicalGrabMovement(pos);
|
NonPhysicalGrabMovement(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//NonPhysicalGrabMovement(pos);
|
NonPhysicalGrabMovement(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply possition for grabbing non-physical linksets (Ctrl+Drag)
|
||||||
|
/// This MUST be blocked for linksets that contain touch scripts because the viewer triggers grab on the touch
|
||||||
|
/// event (Viewer Bug?) This would allow anyone to drag a linkset with a touch script. SL behaviour is also to
|
||||||
|
/// block grab on prims with touch events.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos">New Position</param>
|
||||||
public void NonPhysicalGrabMovement(Vector3 pos)
|
public void NonPhysicalGrabMovement(Vector3 pos)
|
||||||
{
|
{
|
||||||
AbsolutePosition = pos;
|
if(!IsAttachment && ScriptCount() == 0)
|
||||||
m_rootPart.SendTerseUpdateToAllClients();
|
UpdateGroupPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2781,16 +2788,27 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//NonPhysicalSpinMovement(pos);
|
NonPhysicalSpinMovement(newOrientation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//NonPhysicalSpinMovement(pos);
|
NonPhysicalSpinMovement(newOrientation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply rotation for spinning non-physical linksets (Ctrl+Shift+Drag)
|
||||||
|
/// As with dragging, scripted objects must be blocked from spinning
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newOrientation">New Rotation</param>
|
||||||
|
private void NonPhysicalSpinMovement(Quaternion newOrientation)
|
||||||
|
{
|
||||||
|
if(!IsAttachment && ScriptCount() == 0)
|
||||||
|
UpdateGroupRotationR(newOrientation);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the name of a prim
|
/// Set the name of a prim
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Linq;
|
||||||
|
using Nini.Config;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Serialization.External;
|
||||||
|
using OpenSim.Framework.Communications;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Basic scene object serialization tests.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class SceneObjectSerializationTests : OpenSimTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serialize and deserialize.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestSerialDeserial()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
Scene scene = new SceneHelpers().SetupScene();
|
||||||
|
int partsToTestCount = 3;
|
||||||
|
|
||||||
|
SceneObjectGroup so
|
||||||
|
= SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
|
||||||
|
SceneObjectPart[] parts = so.Parts;
|
||||||
|
so.Name = "obj1";
|
||||||
|
so.Description = "xpto";
|
||||||
|
|
||||||
|
string xml = SceneObjectSerializer.ToXml2Format(so);
|
||||||
|
Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string");
|
||||||
|
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.LoadXml(xml);
|
||||||
|
XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart");
|
||||||
|
Assert.That(nodes.Count, Is.EqualTo(3), "SOG serialization resulted in wrong number of SOPs");
|
||||||
|
|
||||||
|
SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml);
|
||||||
|
Assert.IsNotNull(so2, "SOG deserialization resulted in null object");
|
||||||
|
Assert.That(so2.Name == so.Name, "Name of deserialized object does not match original name");
|
||||||
|
Assert.That(so2.Description == so.Description, "Description of deserialized object does not match original name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This checks for a bug reported in mantis #7514
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestNamespaceAttribute()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
|
||||||
|
Scene scene = new SceneHelpers().SetupScene();
|
||||||
|
UserAccount account = new UserAccount(UUID.Zero, UUID.Random(), "Test", "User", string.Empty);
|
||||||
|
scene.UserAccountService.StoreUserAccount(account);
|
||||||
|
int partsToTestCount = 1;
|
||||||
|
|
||||||
|
SceneObjectGroup so
|
||||||
|
= SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
|
||||||
|
SceneObjectPart[] parts = so.Parts;
|
||||||
|
so.Name = "obj1";
|
||||||
|
so.Description = "xpto";
|
||||||
|
so.OwnerID = account.PrincipalID;
|
||||||
|
so.RootPart.CreatorID = so.OwnerID;
|
||||||
|
|
||||||
|
string xml = SceneObjectSerializer.ToXml2Format(so);
|
||||||
|
Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string");
|
||||||
|
|
||||||
|
xml = ExternalRepresentationUtils.RewriteSOP(xml, "Test Scene", "http://localhost", scene.UserAccountService, UUID.Zero);
|
||||||
|
//Console.WriteLine(xml);
|
||||||
|
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.LoadXml(xml);
|
||||||
|
|
||||||
|
XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart");
|
||||||
|
Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no SOPs");
|
||||||
|
foreach (XmlAttribute a in nodes[0].Attributes)
|
||||||
|
{
|
||||||
|
int count = a.Name.Count(c => c == ':');
|
||||||
|
Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in SOP");
|
||||||
|
}
|
||||||
|
nodes = doc.GetElementsByTagName("CreatorData");
|
||||||
|
Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no CreatorData");
|
||||||
|
foreach (XmlAttribute a in nodes[0].Attributes)
|
||||||
|
{
|
||||||
|
int count = a.Name.Count(c => c == ':');
|
||||||
|
Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in CreatorData");
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml);
|
||||||
|
Assert.IsNotNull(so2, "SOG deserialization resulted in null object");
|
||||||
|
Assert.AreNotEqual(so.RootPart.CreatorIdentification, so2.RootPart.CreatorIdentification, "RewriteSOP failed to transform CreatorData.");
|
||||||
|
Assert.That(so2.RootPart.CreatorIdentification.Contains("http://"), "RewriteSOP failed to add the homeURL to CreatorData");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.Region.OptionalModules", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.Region.OptionalModules", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -115,6 +115,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
||||||
|
|
||||||
private delegate T DefaultGetter<T>(string settingName, T defaultValue);
|
private delegate T DefaultGetter<T>(string settingName, T defaultValue);
|
||||||
private bool m_enabled;
|
private bool m_enabled;
|
||||||
|
private ICommandConsole m_console;
|
||||||
|
private List<Scene> m_Scenes = new List<Scene> ();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
|
/// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
|
||||||
|
@ -208,6 +211,18 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
||||||
/// <param name="scene"></param>
|
/// <param name="scene"></param>
|
||||||
void IRegionModuleBase.AddRegion (Scene scene)
|
void IRegionModuleBase.AddRegion (Scene scene)
|
||||||
{
|
{
|
||||||
|
if (!this.m_enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lock (m_Scenes) {
|
||||||
|
m_Scenes.Add (scene);
|
||||||
|
}
|
||||||
|
m_console = MainConsole.Instance;
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand (
|
||||||
|
"AutoBackup", false, "dobackup",
|
||||||
|
"dobackup",
|
||||||
|
"do backup.", DoBackup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -220,7 +235,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m_Scenes.Remove (scene);
|
||||||
if (this.m_states.ContainsKey(scene))
|
if (this.m_states.ContainsKey(scene))
|
||||||
{
|
{
|
||||||
AutoBackupModuleState abms = this.m_states[scene];
|
AutoBackupModuleState abms = this.m_states[scene];
|
||||||
|
@ -275,6 +290,28 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private void DoBackup (string module, string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length != 2) {
|
||||||
|
MainConsole.Instance.OutputFormat ("Usage: dobackup <regionname>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool found = false;
|
||||||
|
string name = args [1];
|
||||||
|
lock (m_Scenes) {
|
||||||
|
foreach (Scene s in m_Scenes) {
|
||||||
|
string test = s.Name.ToString ();
|
||||||
|
if (test == name) {
|
||||||
|
found = true;
|
||||||
|
DoRegionBackup (s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set up internal state for a given scene. Fairly complex code.
|
/// Set up internal state for a given scene. Fairly complex code.
|
||||||
/// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene.
|
/// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene.
|
||||||
|
|
|
@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all values by your own or you can build default build and revision
|
// You can specify all values by your own or you can build default build and revision
|
||||||
// numbers with the '*' character (the default):
|
// numbers with the '*' character (the default):
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all values by your own or you can build default build and revision
|
// You can specify all values by your own or you can build default build and revision
|
||||||
// numbers with the '*' character (the default):
|
// numbers with the '*' character (the default):
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
|
@ -84,7 +84,8 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
private List<List<Vector3>> mConvexHulls = null;
|
private List<List<Vector3>> mConvexHulls = null;
|
||||||
private List<Vector3> mBoundingHull = null;
|
private List<Vector3> mBoundingHull = null;
|
||||||
|
|
||||||
private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
|
// Mesh cache. Static so it can be shared across instances of this class
|
||||||
|
private static Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
|
||||||
|
|
||||||
public Meshmerizer(IConfigSource config)
|
public Meshmerizer(IConfigSource config)
|
||||||
{
|
{
|
||||||
|
@ -927,9 +928,12 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
if (shouldCache)
|
if (shouldCache)
|
||||||
{
|
{
|
||||||
key = primShape.GetMeshKey(size, lod);
|
key = primShape.GetMeshKey(size, lod);
|
||||||
|
lock (m_uniqueMeshes)
|
||||||
|
{
|
||||||
if (m_uniqueMeshes.TryGetValue(key, out mesh))
|
if (m_uniqueMeshes.TryGetValue(key, out mesh))
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (size.X < 0.01f) size.X = 0.01f;
|
if (size.X < 0.01f) size.X = 0.01f;
|
||||||
if (size.Y < 0.01f) size.Y = 0.01f;
|
if (size.Y < 0.01f) size.Y = 0.01f;
|
||||||
|
@ -953,10 +957,13 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
mesh.TrimExcess();
|
mesh.TrimExcess();
|
||||||
|
|
||||||
if (shouldCache)
|
if (shouldCache)
|
||||||
|
{
|
||||||
|
lock (m_uniqueMeshes)
|
||||||
{
|
{
|
||||||
m_uniqueMeshes.Add(key, mesh);
|
m_uniqueMeshes.Add(key, mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all values by your own or you can build default build and revision
|
// You can specify all values by your own or you can build default build and revision
|
||||||
// numbers with the '*' character (the default):
|
// numbers with the '*' character (the default):
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
|
@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all values by your own or you can build default build and revision
|
// You can specify all values by your own or you can build default build and revision
|
||||||
// numbers with the '*' character (the default):
|
// numbers with the '*' character (the default):
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.8.1.*")]
|
[assembly : AssemblyVersion("0.8.2.*")]
|
||||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.RegionModules.RegionCombinerModule", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.RegionModules.RegionCombinerModule", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -596,6 +596,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
public const int OBJECT_PHYSICS = 21;
|
public const int OBJECT_PHYSICS = 21;
|
||||||
public const int OBJECT_PHANTOM = 22;
|
public const int OBJECT_PHANTOM = 22;
|
||||||
public const int OBJECT_TEMP_ON_REZ = 23;
|
public const int OBJECT_TEMP_ON_REZ = 23;
|
||||||
|
public const int OBJECT_RENDER_WEIGHT = 24;
|
||||||
|
public const int OBJECT_HOVER_HEIGHT = 25;
|
||||||
|
public const int OBJECT_BODY_SHAPE_TYPE = 26;
|
||||||
|
public const int OBJECT_LAST_OWNER_ID = 27;
|
||||||
|
|
||||||
// Pathfinding types
|
// Pathfinding types
|
||||||
public const int OPT_OTHER = -1;
|
public const int OPT_OTHER = -1;
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ using Mono.Addins;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.Region.ScriptEngine.XEngine", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: Addin("OpenSim.Region.ScriptEngine.XEngine", OpenSim.VersionInfo.VersionNumber)]
|
||||||
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,9 @@ namespace OpenSim.Server.Base
|
||||||
argvConfig.AddSwitch("Startup", "logconfig", "g");
|
argvConfig.AddSwitch("Startup", "logconfig", "g");
|
||||||
|
|
||||||
// Automagically create the ini file name
|
// Automagically create the ini file name
|
||||||
string fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
|
string fileName = "";
|
||||||
|
if (Assembly.GetEntryAssembly() != null)
|
||||||
|
fileName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
|
||||||
string iniFile = fileName + ".ini";
|
string iniFile = fileName + ".ini";
|
||||||
string logConfig = null;
|
string logConfig = null;
|
||||||
|
|
||||||
|
@ -158,7 +160,11 @@ namespace OpenSim.Server.Base
|
||||||
MainConsole.Instance = new RemoteConsole(prompt);
|
MainConsole.Instance = new RemoteConsole(prompt);
|
||||||
((RemoteConsole)MainConsole.Instance).ReadConfig(Config);
|
((RemoteConsole)MainConsole.Instance).ReadConfig(Config);
|
||||||
}
|
}
|
||||||
else
|
else if (consoleType == "mock")
|
||||||
|
{
|
||||||
|
MainConsole.Instance = new MockConsole();
|
||||||
|
}
|
||||||
|
else if (consoleType == "local")
|
||||||
{
|
{
|
||||||
MainConsole.Instance = new LocalConsole(prompt, startupConfig);
|
MainConsole.Instance = new LocalConsole(prompt, startupConfig);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,9 @@ using OpenSim.Server.Handlers.Base;
|
||||||
using log4net;
|
using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Server.Handlers.Asset
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace OpenSim.Server.Handlers.Inventory
|
||||||
{
|
{
|
||||||
public class XInventoryInConnector : ServiceConnector
|
public class XInventoryInConnector : ServiceConnector
|
||||||
{
|
{
|
||||||
|
@ -123,6 +125,8 @@ namespace OpenSim.Server.Handlers.Asset
|
||||||
return HandleGetFolderForType(request);
|
return HandleGetFolderForType(request);
|
||||||
case "GETFOLDERCONTENT":
|
case "GETFOLDERCONTENT":
|
||||||
return HandleGetFolderContent(request);
|
return HandleGetFolderContent(request);
|
||||||
|
case "GETMULTIPLEFOLDERSCONTENT":
|
||||||
|
return HandleGetMultipleFoldersContent(request);
|
||||||
case "GETFOLDERITEMS":
|
case "GETFOLDERITEMS":
|
||||||
return HandleGetFolderItems(request);
|
return HandleGetFolderItems(request);
|
||||||
case "ADDFOLDER":
|
case "ADDFOLDER":
|
||||||
|
@ -145,6 +149,8 @@ namespace OpenSim.Server.Handlers.Asset
|
||||||
return HandleDeleteItems(request);
|
return HandleDeleteItems(request);
|
||||||
case "GETITEM":
|
case "GETITEM":
|
||||||
return HandleGetItem(request);
|
return HandleGetItem(request);
|
||||||
|
case "GETMULTIPLEITEMS":
|
||||||
|
return HandleGetMultipleItems(request);
|
||||||
case "GETFOLDER":
|
case "GETFOLDER":
|
||||||
return HandleGetFolder(request);
|
return HandleGetFolder(request);
|
||||||
case "GETACTIVEGESTURES":
|
case "GETACTIVEGESTURES":
|
||||||
|
@ -284,6 +290,8 @@ namespace OpenSim.Server.Handlers.Asset
|
||||||
InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID);
|
InventoryCollection icoll = m_InventoryService.GetFolderContent(principal, folderID);
|
||||||
if (icoll != null)
|
if (icoll != null)
|
||||||
{
|
{
|
||||||
|
result["FID"] = icoll.FolderID.ToString();
|
||||||
|
result["VERSION"] = icoll.Version.ToString();
|
||||||
Dictionary<string, object> folders = new Dictionary<string, object>();
|
Dictionary<string, object> folders = new Dictionary<string, object>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (icoll.Folders != null)
|
if (icoll.Folders != null)
|
||||||
|
@ -314,6 +322,70 @@ namespace OpenSim.Server.Handlers.Asset
|
||||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetMultipleFoldersContent(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> resultSet = new Dictionary<string, object>();
|
||||||
|
UUID principal = UUID.Zero;
|
||||||
|
UUID.TryParse(request["PRINCIPAL"].ToString(), out principal);
|
||||||
|
string folderIDstr = request["FOLDERS"].ToString();
|
||||||
|
int count = 0;
|
||||||
|
Int32.TryParse(request["COUNT"].ToString(), out count);
|
||||||
|
|
||||||
|
UUID[] fids = new UUID[count];
|
||||||
|
string[] uuids = folderIDstr.Split(',');
|
||||||
|
int i = 0;
|
||||||
|
foreach (string id in uuids)
|
||||||
|
{
|
||||||
|
UUID fid = UUID.Zero;
|
||||||
|
if (UUID.TryParse(id, out fid))
|
||||||
|
fids[i] = fid;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
InventoryCollection[] icollList = m_InventoryService.GetMultipleFoldersContent(principal, fids);
|
||||||
|
if (icollList != null && icollList.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (InventoryCollection icoll in icollList)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
result["FID"] = icoll.FolderID.ToString();
|
||||||
|
result["VERSION"] = icoll.Version.ToString();
|
||||||
|
result["OWNER"] = icoll.OwnerID.ToString();
|
||||||
|
Dictionary<string, object> folders = new Dictionary<string, object>();
|
||||||
|
i = 0;
|
||||||
|
if (icoll.Folders != null)
|
||||||
|
{
|
||||||
|
foreach (InventoryFolderBase f in icoll.Folders)
|
||||||
|
{
|
||||||
|
folders["folder_" + i.ToString()] = EncodeFolder(f);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
result["FOLDERS"] = folders;
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
if (icoll.Items != null)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> items = new Dictionary<string, object>();
|
||||||
|
foreach (InventoryItemBase it in icoll.Items)
|
||||||
|
{
|
||||||
|
items["item_" + i.ToString()] = EncodeItem(it);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
result["ITEMS"] = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultSet["F_" + fids[count++]] = result;
|
||||||
|
//m_log.DebugFormat("[XXX]: Sending {0} {1}", fids[count-1], icoll.FolderID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(resultSet);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] HandleGetFolderItems(Dictionary<string, object> request)
|
byte[] HandleGetFolderItems(Dictionary<string, object> request)
|
||||||
{
|
{
|
||||||
Dictionary<string,object> result = new Dictionary<string,object>();
|
Dictionary<string,object> result = new Dictionary<string,object>();
|
||||||
|
@ -506,6 +578,40 @@ namespace OpenSim.Server.Handlers.Asset
|
||||||
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetMultipleItems(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> resultSet = new Dictionary<string, object>();
|
||||||
|
UUID principal = UUID.Zero;
|
||||||
|
UUID.TryParse(request["PRINCIPAL"].ToString(), out principal);
|
||||||
|
string itemIDstr = request["ITEMS"].ToString();
|
||||||
|
int count = 0;
|
||||||
|
Int32.TryParse(request["COUNT"].ToString(), out count);
|
||||||
|
|
||||||
|
UUID[] fids = new UUID[count];
|
||||||
|
string[] uuids = itemIDstr.Split(',');
|
||||||
|
int i = 0;
|
||||||
|
foreach (string id in uuids)
|
||||||
|
{
|
||||||
|
UUID fid = UUID.Zero;
|
||||||
|
if (UUID.TryParse(id, out fid))
|
||||||
|
fids[i] = fid;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryItemBase[] itemsList = m_InventoryService.GetMultipleItems(principal, fids);
|
||||||
|
if (itemsList != null && itemsList.Length > 0)
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
foreach (InventoryItemBase item in itemsList)
|
||||||
|
resultSet["item_" + count++] = (item == null) ? (object)"NULL" : EncodeItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(resultSet);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] HandleGetFolder(Dictionary<string,object> request)
|
byte[] HandleGetFolder(Dictionary<string,object> request)
|
||||||
{
|
{
|
||||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -257,8 +257,7 @@ namespace OpenSim.Server.Handlers.UserAccounts
|
||||||
|
|
||||||
byte[] CreateUser(Dictionary<string, object> request)
|
byte[] CreateUser(Dictionary<string, object> request)
|
||||||
{
|
{
|
||||||
if (!
|
if (! request.ContainsKey("FirstName")
|
||||||
request.ContainsKey("FirstName")
|
|
||||||
&& request.ContainsKey("LastName")
|
&& request.ContainsKey("LastName")
|
||||||
&& request.ContainsKey("Password"))
|
&& request.ContainsKey("Password"))
|
||||||
return FailureResult();
|
return FailureResult();
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ using OpenSim.Services.Connectors;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
using OpenSim.Server.Base;
|
using OpenSim.Server.Base;
|
||||||
|
|
||||||
namespace OpenSim.Service.Connectors
|
namespace OpenSim.Services.Connectors
|
||||||
{
|
{
|
||||||
public class EstateDataRemoteConnector : BaseServiceConnector, IEstateDataService
|
public class EstateDataRemoteConnector : BaseServiceConnector, IEstateDataService
|
||||||
{
|
{
|
||||||
|
|
|
@ -205,7 +205,7 @@ namespace OpenSim.Services.Connectors
|
||||||
InventoryCollection inventory = new InventoryCollection();
|
InventoryCollection inventory = new InventoryCollection();
|
||||||
inventory.Folders = new List<InventoryFolderBase>();
|
inventory.Folders = new List<InventoryFolderBase>();
|
||||||
inventory.Items = new List<InventoryItemBase>();
|
inventory.Items = new List<InventoryItemBase>();
|
||||||
inventory.UserID = principalID;
|
inventory.OwnerID = principalID;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -236,6 +236,87 @@ namespace OpenSim.Services.Connectors
|
||||||
return inventory;
|
return inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
|
||||||
|
{
|
||||||
|
InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length];
|
||||||
|
//m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", folderIDs.Length);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT",
|
||||||
|
new Dictionary<string, object> {
|
||||||
|
{ "PRINCIPAL", principalID.ToString() },
|
||||||
|
{ "FOLDERS", String.Join(",", folderIDs) },
|
||||||
|
{ "COUNT", folderIDs.Length.ToString() }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!CheckReturn(resultSet))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (KeyValuePair<string, object> kvp in resultSet)
|
||||||
|
{
|
||||||
|
InventoryCollection inventory = new InventoryCollection();
|
||||||
|
if (kvp.Key.StartsWith("F_"))
|
||||||
|
{
|
||||||
|
UUID fid = UUID.Zero;
|
||||||
|
if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i])
|
||||||
|
{
|
||||||
|
inventory.Folders = new List<InventoryFolderBase>();
|
||||||
|
inventory.Items = new List<InventoryItemBase>();
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = (Dictionary<string, object>)kvp.Value;
|
||||||
|
|
||||||
|
if (ret.ContainsKey("FID"))
|
||||||
|
{
|
||||||
|
if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID))
|
||||||
|
m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response");
|
||||||
|
|
||||||
|
inventory.Version = -1;
|
||||||
|
if (ret.ContainsKey("VERSION"))
|
||||||
|
Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version);
|
||||||
|
if (ret.ContainsKey("OWNER"))
|
||||||
|
UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID);
|
||||||
|
|
||||||
|
Dictionary<string, object> folders =
|
||||||
|
(Dictionary<string, object>)ret["FOLDERS"];
|
||||||
|
Dictionary<string, object> items =
|
||||||
|
(Dictionary<string, object>)ret["ITEMS"];
|
||||||
|
|
||||||
|
foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
|
||||||
|
{
|
||||||
|
inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
|
||||||
|
}
|
||||||
|
foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
|
||||||
|
{
|
||||||
|
inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
|
||||||
|
}
|
||||||
|
|
||||||
|
inventoryArr[i] = inventory;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}",
|
||||||
|
folderIDs[i], fid);
|
||||||
|
m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys));
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inventoryArr;
|
||||||
|
}
|
||||||
|
|
||||||
public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
|
public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
|
||||||
{
|
{
|
||||||
Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
|
Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
|
||||||
|
@ -325,8 +406,12 @@ namespace OpenSim.Services.Connectors
|
||||||
|
|
||||||
public bool AddItem(InventoryItemBase item)
|
public bool AddItem(InventoryItemBase item)
|
||||||
{
|
{
|
||||||
|
if (item.Description == null)
|
||||||
|
item.Description = String.Empty;
|
||||||
if (item.CreatorData == null)
|
if (item.CreatorData == null)
|
||||||
item.CreatorData = String.Empty;
|
item.CreatorData = String.Empty;
|
||||||
|
if (item.CreatorId == null)
|
||||||
|
item.CreatorId = String.Empty;
|
||||||
Dictionary<string, object> ret = MakeRequest("ADDITEM",
|
Dictionary<string, object> ret = MakeRequest("ADDITEM",
|
||||||
new Dictionary<string,object> {
|
new Dictionary<string,object> {
|
||||||
{ "AssetID", item.AssetID.ToString() },
|
{ "AssetID", item.AssetID.ToString() },
|
||||||
|
@ -446,6 +531,42 @@ namespace OpenSim.Services.Connectors
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
|
||||||
|
{
|
||||||
|
InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEITEMS",
|
||||||
|
new Dictionary<string, object> {
|
||||||
|
{ "PRINCIPAL", principalID.ToString() },
|
||||||
|
{ "ITEMS", String.Join(",", itemIDs) },
|
||||||
|
{ "COUNT", itemIDs.Length.ToString() }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!CheckReturn(resultSet))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (KeyValuePair<string, object> kvp in resultSet)
|
||||||
|
{
|
||||||
|
InventoryCollection inventory = new InventoryCollection();
|
||||||
|
if (kvp.Key.StartsWith("item_"))
|
||||||
|
{
|
||||||
|
if (kvp.Value is Dictionary<string, object>)
|
||||||
|
itemArr[i++] = BuildItem((Dictionary<string, object>)kvp.Value);
|
||||||
|
else
|
||||||
|
itemArr[i++] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemArr;
|
||||||
|
}
|
||||||
|
|
||||||
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -301,6 +301,21 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
|
||||||
|
{
|
||||||
|
InventoryItemBase[] result = new InventoryItemBase[itemIDs.Length];
|
||||||
|
int i = 0;
|
||||||
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
item.Owner = principalID;
|
||||||
|
foreach (UUID id in itemIDs)
|
||||||
|
{
|
||||||
|
item.ID = id;
|
||||||
|
result[i++] = GetItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a folder, given by its UUID
|
/// Get a folder, given by its UUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -340,7 +355,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
|
public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
|
||||||
{
|
{
|
||||||
InventoryCollection inventory = new InventoryCollection();
|
InventoryCollection inventory = new InventoryCollection();
|
||||||
inventory.UserID = userID;
|
inventory.OwnerID = userID;
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
|
@ -371,6 +386,18 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
return inventory;
|
return inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
|
||||||
|
{
|
||||||
|
InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
|
||||||
|
int i = 0;
|
||||||
|
foreach (UUID fid in folderIDs)
|
||||||
|
{
|
||||||
|
invColl[i++] = GetFolderContent(principalID, fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return invColl;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the items inside a folder
|
/// Gets the items inside a folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -380,7 +407,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
|
||||||
{
|
{
|
||||||
InventoryCollection inventory = new InventoryCollection();
|
InventoryCollection inventory = new InventoryCollection();
|
||||||
inventory.UserID = userID;
|
inventory.OwnerID = userID;
|
||||||
|
|
||||||
NameValueCollection requestArgs = new NameValueCollection
|
NameValueCollection requestArgs = new NameValueCollection
|
||||||
{
|
{
|
||||||
|
|
|
@ -215,7 +215,37 @@ namespace OpenSim.Services.Connectors
|
||||||
sendData[kvp.Key] = kvp.Value.ToString();
|
sendData[kvp.Key] = kvp.Value.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendAndGetBoolReply(sendData);
|
if (SendAndGetReply(sendData) != null)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create user remotely. Note this this is not part of the IUserAccountsService
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="first"></param>
|
||||||
|
/// <param name="last"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <param name="email"></param>
|
||||||
|
/// <param name="scopeID"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual UserAccount CreateUser(string first, string last, string password, string email, UUID scopeID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
//sendData["SCOPEID"] = scopeID.ToString();
|
||||||
|
sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
|
||||||
|
sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
|
||||||
|
sendData["METHOD"] = "createuser";
|
||||||
|
|
||||||
|
sendData["FirstName"] = first;
|
||||||
|
sendData["LastName"] = last;
|
||||||
|
sendData["Password"] = password;
|
||||||
|
if (!string.IsNullOrEmpty(email))
|
||||||
|
sendData["Email"] = first;
|
||||||
|
sendData["ScopeID"] = scopeID.ToString();
|
||||||
|
|
||||||
|
return SendAndGetReply(sendData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserAccount SendAndGetReply(Dictionary<string, object> sendData)
|
private UserAccount SendAndGetReply(Dictionary<string, object> sendData)
|
||||||
|
@ -269,6 +299,7 @@ namespace OpenSim.Services.Connectors
|
||||||
m_Auth);
|
m_Auth);
|
||||||
if (reply != string.Empty)
|
if (reply != string.Empty)
|
||||||
{
|
{
|
||||||
|
//m_log.DebugFormat("[ACCOUNTS CONNECTOR]: reply = {0}", reply);
|
||||||
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
|
||||||
|
|
||||||
if (replyData.ContainsKey("result"))
|
if (replyData.ContainsKey("result"))
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ namespace OpenSim.Services.HypergridService
|
||||||
protected byte[] AdjustIdentifiers(byte[] data)
|
protected byte[] AdjustIdentifiers(byte[] data)
|
||||||
{
|
{
|
||||||
string xml = Utils.BytesToString(data);
|
string xml = Utils.BytesToString(data);
|
||||||
return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, m_HomeURL, m_Cache, UUID.Zero));
|
return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, "HGAssetService", m_HomeURL, m_Cache, UUID.Zero));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,14 @@ namespace OpenSim.Services.HypergridService
|
||||||
Object[] args = new Object[] { config };
|
Object[] args = new Object[] { config };
|
||||||
m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
|
m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
|
||||||
m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
|
m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
|
||||||
|
try
|
||||||
|
{
|
||||||
m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(userAgentService, args);
|
m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(userAgentService, args);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[HG IM SERVICE]: Unable to create User Agent Service. Missing config var in [HGInstantMessageService]?");
|
||||||
|
}
|
||||||
|
|
||||||
m_RegionCache = new ExpiringCache<UUID, GridRegion>();
|
m_RegionCache = new ExpiringCache<UUID, GridRegion>();
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,13 @@ namespace OpenSim.Services.HypergridService
|
||||||
//{
|
//{
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
// NOGO
|
||||||
|
//
|
||||||
|
public override InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderID)
|
||||||
|
{
|
||||||
|
return new InventoryCollection[0];
|
||||||
|
}
|
||||||
|
|
||||||
//public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
|
//public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
|
||||||
//{
|
//{
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.8.1.*")]
|
[assembly: AssemblyVersion("0.8.2.*")]
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue