From ec4f981f1d371b329d227e17cb2f5aaaba364fad Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 25 Apr 2013 01:39:22 +0200 Subject: [PATCH 1/4] Adding the dynamic menu module which allows registering new menu options in compliant viewers --- .../Interfaces/IDynamicMenuModule.cs | 57 ++++ .../ViewerSupport/DynamicMenuModule.cs | 282 ++++++++++++++++++ 2 files changed, 339 insertions(+) create mode 100644 OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs create mode 100644 OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs new file mode 100644 index 0000000000..08b71e44b1 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs @@ -0,0 +1,57 @@ +/* + * 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.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + public enum InsertLocation : int + { + Agent = 1, + World = 2, + Tools = 3, + Advanced = 4, + Admin = 5 + } + + public enum UserMode : int + { + Normal = 0, + God = 3 + } + + public delegate void CustomMenuHandler(string action, UUID agentID, List selection); + + public interface IDynamicMenuModule + { + void AddMenuItem(UUID agentID, string title, InsertLocation location, UserMode mode, CustomMenuHandler handler); + void AddMenuItem(string title, InsertLocation location, UserMode mode, CustomMenuHandler handler); + void RemoveMenuItem(string action); + } +} diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs new file mode 100644 index 0000000000..917911f9ca --- /dev/null +++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs @@ -0,0 +1,282 @@ +// ****************************************************************** +// Copyright (c) 2008, 2009 Melanie Thielker +// +// All rights reserved +// + +using System; +using System.IO; +using System.Reflection; +using System.Text; +using System.Collections.Generic; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim; +using OpenSim.Region; +using OpenSim.Region.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Framework; +//using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using Nini.Config; +using log4net; +using Mono.Addins; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; + +namespace OpenSim.Region.OptionalModules.ViewerSupport +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicMenu")] + public class DynamicMenuModule : INonSharedRegionModule, IDynamicMenuModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private class MenuItemData + { + public string Title; + public UUID AgentID; + public InsertLocation Location; + public UserMode Mode; + public CustomMenuHandler Handler; + } + + private Dictionary> m_menuItems = + new Dictionary>(); + + private Scene m_scene; + + public string Name + { + get { return "DynamicMenuModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void Initialise(IConfigSource config) + { + } + + public void Close() + { + } + + public void AddRegion(Scene scene) + { + m_scene = scene; + scene.EventManager.OnRegisterCaps += OnRegisterCaps; + m_scene.RegisterModuleInterface(this); + } + + public void RegionLoaded(Scene scene) + { + ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface(); + + if (featuresModule != null) + featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest; + } + + public void RemoveRegion(Scene scene) + { + } + + private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) + { + OSD menus = new OSDMap(); + if (features.ContainsKey("menus")) + menus = features["menus"]; + + OSDMap agent = new OSDMap(); + OSDMap world = new OSDMap(); + OSDMap tools = new OSDMap(); + OSDMap advanced = new OSDMap(); + OSDMap admin = new OSDMap(); + if (((OSDMap)menus).ContainsKey("agent")) + agent = (OSDMap)((OSDMap)menus)["agent"]; + if (((OSDMap)menus).ContainsKey("world")) + world = (OSDMap)((OSDMap)menus)["world"]; + if (((OSDMap)menus).ContainsKey("tools")) + tools = (OSDMap)((OSDMap)menus)["tools"]; + if (((OSDMap)menus).ContainsKey("advanced")) + advanced = (OSDMap)((OSDMap)menus)["advanced"]; + if (((OSDMap)menus).ContainsKey("admin")) + admin = (OSDMap)((OSDMap)menus)["admin"]; + + if (m_menuItems.ContainsKey(UUID.Zero)) + { + foreach (MenuItemData d in m_menuItems[UUID.Zero]) + { + if (d.Mode == UserMode.God && (!m_scene.Permissions.IsGod(agentID))) + continue; + + OSDMap loc = null; + switch (d.Location) + { + case InsertLocation.Agent: + loc = agent; + break; + case InsertLocation.World: + loc = world; + break; + case InsertLocation.Tools: + loc = tools; + break; + case InsertLocation.Advanced: + loc = advanced; + break; + case InsertLocation.Admin: + loc = admin; + break; + } + + if (loc == null) + continue; + + loc[d.Title] = OSD.FromString(d.Title); + } + } + + if (m_menuItems.ContainsKey(agentID)) + { + foreach (MenuItemData d in m_menuItems[agentID]) + { + if (d.Mode == UserMode.God && (!m_scene.Permissions.IsGod(agentID))) + continue; + + OSDMap loc = null; + switch (d.Location) + { + case InsertLocation.Agent: + loc = agent; + break; + case InsertLocation.World: + loc = world; + break; + case InsertLocation.Tools: + loc = tools; + break; + case InsertLocation.Advanced: + loc = advanced; + break; + case InsertLocation.Admin: + loc = admin; + break; + } + + if (loc == null) + continue; + + loc[d.Title] = OSD.FromString(d.Title); + } + } + + + ((OSDMap)menus)["agent"] = agent; + ((OSDMap)menus)["world"] = world; + ((OSDMap)menus)["tools"] = tools; + ((OSDMap)menus)["advanced"] = advanced; + ((OSDMap)menus)["admin"] = admin; + + features["menus"] = menus; + } + + private void OnRegisterCaps(UUID agentID, Caps caps) + { + string capUrl = "/CAPS/" + UUID.Random() + "/"; + + capUrl = "/CAPS/" + UUID.Random() + "/"; + caps.RegisterHandler("CustomMenuAction", new MenuActionHandler(capUrl, "CustomMenuAction", agentID, this, m_scene)); + } + + internal void HandleMenuSelection(string action, UUID agentID, List selection) + { + if (m_menuItems.ContainsKey(agentID)) + { + foreach (MenuItemData d in m_menuItems[agentID]) + { + if (d.Title == action) + d.Handler(action, agentID, selection); + } + } + + if (m_menuItems.ContainsKey(UUID.Zero)) + { + foreach (MenuItemData d in m_menuItems[UUID.Zero]) + { + if (d.Title == action) + d.Handler(action, agentID, selection); + } + } + } + + public void AddMenuItem(string title, InsertLocation location, UserMode mode, CustomMenuHandler handler) + { + AddMenuItem(UUID.Zero, title, location, mode, handler); + } + + public void AddMenuItem(UUID agentID, string title, InsertLocation location, UserMode mode, CustomMenuHandler handler) + { + if (!m_menuItems.ContainsKey(agentID)) + m_menuItems[agentID] = new List(); + + m_menuItems[agentID].Add(new MenuItemData() { Title = title, AgentID = agentID, Location = location, Mode = mode, Handler = handler }); + } + + public void RemoveMenuItem(string action) + { + foreach (KeyValuePair> kvp in m_menuItems) + { + List pendingDeletes = new List(); + foreach (MenuItemData d in kvp.Value) + { + if (d.Title == action) + pendingDeletes.Add(d); + } + + foreach (MenuItemData d in pendingDeletes) + kvp.Value.Remove(d); + } + } + } + + public class MenuActionHandler : BaseStreamHandler + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private UUID m_agentID; + private Scene m_scene; + private DynamicMenuModule m_module; + + public MenuActionHandler(string path, string name, UUID agentID, DynamicMenuModule module, Scene scene) + :base("POST", path, name, agentID.ToString()) + { + m_agentID = agentID; + m_scene = scene; + m_module = module; + } + + public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + StreamReader reader = new StreamReader(request); + string requestBody = reader.ReadToEnd(); + + OSD osd = OSDParser.DeserializeLLSDXml(requestBody); + + string action = ((OSDMap)osd)["action"].AsString(); + OSDArray selection = (OSDArray)((OSDMap)osd)["selection"]; + List sel = new List(); + for (int i = 0 ; i < selection.Count ; i++) + sel.Add(selection[i].AsUInteger()); + + Util.FireAndForget(x => { m_module.HandleMenuSelection(action, m_agentID, sel); }); + + Encoding encoding = Encoding.UTF8; + return encoding.GetBytes(OSDParser.SerializeLLSDXmlString(new OSD())); + } + } +} From 0e22021c650a84ae1b9ed86d7c8df3beeb6e54ed Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 24 Apr 2013 19:00:41 -0700 Subject: [PATCH 2/4] Make the kicked user's avie truly disappear when it's god-kicked. --- OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index d9badcd90a..16673ec448 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs @@ -276,8 +276,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods if (sp.IsChildAgent) return; sp.ControllingClient.Kick(reason); - sp.MakeChildAgent(); - sp.ControllingClient.Close(); + sp.Scene.IncomingCloseAgent(sp.UUID, true); } private void OnIncomingInstantMessage(GridInstantMessage msg) From c10405330d0fa5855c3f8180fdc8347cb87fed4f Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 24 Apr 2013 20:43:15 -0700 Subject: [PATCH 3/4] UUIDGatherer now includes UUIDs which reference texture assets used as materials --- .../Region/Framework/Scenes/UuidGatherer.cs | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index ad33607139..0e83781d19 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -34,6 +34,7 @@ using System.Threading; using log4net; using OpenMetaverse; using OpenMetaverse.Assets; +using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; @@ -184,6 +185,9 @@ namespace OpenSim.Region.Framework.Scenes if (!assetUuids.ContainsKey(tii.AssetID)) GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); } + + // get any texture UUIDs used for materials such as normal and specular maps + GatherMaterialsUuids(part, assetUuids); } catch (Exception e) { @@ -208,6 +212,68 @@ namespace OpenSim.Region.Framework.Scenes // } // } + + /// + /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps + /// + /// + /// + public void GatherMaterialsUuids(SceneObjectPart part, IDictionary assetUuids) + { + // scan thru the dynAttrs map of this part for any textures used as materials + OSDMap OSMaterials = null; + + lock (part.DynAttrs) + { + if (part.DynAttrs.ContainsKey("OS:Materials")) + OSMaterials = part.DynAttrs["OS:Materials"]; + if (OSMaterials != null && OSMaterials.ContainsKey("Materials")) + { + OSD osd = OSMaterials["Materials"]; + //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd)); + + if (osd is OSDArray) + { + OSDArray matsArr = osd as OSDArray; + foreach (OSDMap matMap in matsArr) + { + try + { + if (matMap.ContainsKey("Material")) + { + OSDMap mat = matMap["Material"] as OSDMap; + if (mat.ContainsKey("NormMap")) + { + UUID normalMapId = mat["NormMap"].AsUUID(); + if (normalMapId != UUID.Zero) + { + assetUuids[normalMapId] = AssetType.Texture; + //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); + } + } + if (mat.ContainsKey("SpecMap")) + { + UUID specularMapId = mat["SpecMap"].AsUUID(); + if (specularMapId != UUID.Zero) + { + assetUuids[specularMapId] = AssetType.Texture; + //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); + } + } + } + + } + catch (Exception e) + { + m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message); + } + } + } + } + } + } + + /// /// Get an asset synchronously, potentially using an asynchronous callback. If the /// asynchronous callback is used, we will wait for it to complete. From 3bc801746466cbd401f481295876b357fa27125b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 25 Apr 2013 09:23:15 -0700 Subject: [PATCH 4/4] Recover a lost "virtual". Downstream projects need this. --- OpenSim/Data/MySQL/MySQLSimulationData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 9cc6f400e1..2d20eaf69c 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -52,7 +52,7 @@ namespace OpenSim.Data.MySQL private string m_connectionString; private object m_dbLock = new object(); - protected Assembly Assembly + protected virtual Assembly Assembly { get { return GetType().Assembly; } }