diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 9f3844bf38..49fc5663a5 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -70,6 +70,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController private string m_name = "RemoteAdminPlugin"; private string m_version = "0.0"; + private string m_openSimVersion; public string Version { @@ -89,6 +90,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController public void Initialise(OpenSimBase openSim) { + m_openSimVersion = openSim.GetVersionText(); + m_configSource = openSim.ConfigSource.Source; try { @@ -159,6 +162,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController // Misc availableMethods["admin_refresh_search"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshSearch); + availableMethods["admin_get_opensim_version"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetOpenSimVersion); // Either enable full remote functionality or just selected features string enabledMethods = m_config.GetString("enabled_methods", "all"); @@ -1977,6 +1981,18 @@ namespace OpenSim.ApplicationPlugins.RemoteController m_log.Info("[RADMIN]: Refresh Search Request complete"); } + private void XmlRpcGetOpenSimVersion(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Get OpenSim Version Request"); + + Hashtable responseData = (Hashtable)response.Value; + + responseData["version"] = m_openSimVersion; + responseData["success"] = true; + + m_log.Info("[RADMIN]: Get OpenSim Version Request complete"); + } + /// /// Parse a float with the given parameter name from a request data hash table. /// diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index 6437d0b7b0..68686c5648 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs @@ -99,12 +99,23 @@ namespace OpenSim.Capabilities.Handlers } // OK, we have an array with preferred formats, possibly with only one entry - + bool foundtexture = false; foreach (string f in formats) { - if (FetchTexture(request, ret, textureID, f)) + foundtexture = FetchTexture(request, ret, textureID, f); + if (foundtexture) break; } + if (!foundtexture) + { + ret["int_response_code"] = 404; + ret["error_status_text"] = "not found"; + ret["str_response_string"] = "not found"; + ret["content_type"] = "text/plain"; + ret["keepalive"] = false; + ret["reusecontext"] = false; + ret["int_bytes"] = 0; + } } else { @@ -176,9 +187,13 @@ namespace OpenSim.Capabilities.Handlers return true; } + //response = new Hashtable(); + + + //WriteTextureData(request,response,null,format); // not found -// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); - return true; + //m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); + return false; } private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format) diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index ffc3527035..041fb94ff1 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -1558,7 +1558,58 @@ namespace OpenSim.Framework SHAPE_EYELID_INNER_CORNER_UP = 214, SKIRT_SKIRT_RED = 215, SKIRT_SKIRT_GREEN = 216, - SKIRT_SKIRT_BLUE = 217 + SKIRT_SKIRT_BLUE = 217, + + /// + /// Avatar Physics section. These are 0 type visual params which get transmitted. + /// + + /// + /// Breast Part 1 + /// + BREAST_PHYSICS_MASS = 218, + BREAST_PHYSICS_GRAVITY = 219, + BREAST_PHYSICS_DRAG = 220, + BREAST_PHYSICS_UPDOWN_MAX_EFFECT = 221, + BREAST_PHYSICS_UPDOWN_SPRING = 222, + BREAST_PHYSICS_UPDOWN_GAIN = 223, + BREAST_PHYSICS_UPDOWN_DAMPING = 224, + BREAST_PHYSICS_INOUT_MAX_EFFECT = 225, + BREAST_PHYSICS_INOUT_SPRING = 226, + BREAST_PHYSICS_INOUT_GAIN = 227, + BREAST_PHYSICS_INOUT_DAMPING = 228, + /// + /// Belly + /// + BELLY_PHYISCS_MASS = 229, + BELLY_PHYSICS_GRAVITY = 230, + BELLY_PHYSICS_DRAG = 231, + BELLY_PHYISCS_UPDOWN_MAX_EFFECT = 232, + BELLY_PHYSICS_UPDOWN_SPRING = 233, + BELLY_PHYSICS_UPDOWN_GAIN = 234, + BELLY_PHYSICS_UPDOWN_DAMPING = 235, + + /// + /// Butt + /// + BUTT_PHYSICS_MASS = 236, + BUTT_PHYSICS_GRAVITY = 237, + BUTT_PHYSICS_DRAG = 238, + BUTT_PHYSICS_UPDOWN_MAX_EFFECT = 239, + BUTT_PHYSICS_UPDOWN_SPRING = 240, + BUTT_PHYSICS_UPDOWN_GAIN = 241, + BUTT_PHYSICS_UPDOWN_DAMPING = 242, + BUTT_PHYSICS_LEFTRIGHT_MAX_EFFECT = 243, + BUTT_PHYSICS_LEFTRIGHT_SPRING = 244, + BUTT_PHYSICS_LEFTRIGHT_GAIN = 245, + BUTT_PHYSICS_LEFTRIGHT_DAMPING = 246, + /// + /// Breast Part 2 + /// + BREAST_PHYSICS_LEFTRIGHT_MAX_EFFECT = 247, + BREAST_PHYSICS_LEFTRIGHT_SPRING= 248, + BREAST_PHYSICS_LEFTRIGHT_GAIN = 249, + BREAST_PHYSICS_LEFTRIGHT_DAMPING = 250 } #endregion } diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs index 84f887cc4d..9bd9baf321 100644 --- a/OpenSim/Framework/LocklessQueue.cs +++ b/OpenSim/Framework/LocklessQueue.cs @@ -29,7 +29,7 @@ using System.Threading; namespace OpenSim.Framework { - public sealed class LocklessQueue + public class LocklessQueue { private sealed class SingleLinkNode { @@ -41,7 +41,7 @@ namespace OpenSim.Framework SingleLinkNode tail; int count; - public int Count { get { return count; } } + public virtual int Count { get { return count; } } public LocklessQueue() { @@ -76,7 +76,7 @@ namespace OpenSim.Framework Interlocked.Increment(ref count); } - public bool Dequeue(out T item) + public virtual bool Dequeue(out T item) { item = default(T); SingleLinkNode oldHead = null; @@ -136,4 +136,4 @@ namespace OpenSim.Framework (object)Interlocked.CompareExchange(ref location, newValue, comparand); } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index c182a3abca..9eb2281914 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -531,7 +531,7 @@ namespace OpenSim.Framework.Servers } } - protected string GetVersionText() + public string GetVersionText() { return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion); } @@ -563,4 +563,4 @@ namespace OpenSim.Framework.Servers m_console.OutputFormat(format, components); } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index ca4b126c97..87899f0870 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs @@ -47,6 +47,8 @@ namespace OpenSim.Framework Texture = 5, /// Non-texture assets Asset = 6, + + HighPriority = 128, } [Flags] diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 956c2c9377..fd82db703b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -897,32 +897,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP msg.MessageBlock.Message = Util.StringToBytes1024(im.message); msg.MessageBlock.BinaryBucket = im.binaryBucket; - if (im.message.StartsWith("[grouptest]")) - { // this block is test code for implementing group IM - delete when group IM is finished - IEventQueue eq = Scene.RequestModuleInterface(); - if (eq != null) - { - im.dialog = 17; - - //eq.ChatterboxInvitation( - // new UUID("00000000-68f9-1111-024e-222222111123"), - // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0, - // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket); - - eq.ChatterboxInvitation( - new UUID("00000000-68f9-1111-024e-222222111123"), - "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0, - false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing")); - - eq.ChatterBoxSessionAgentListUpdates( - new UUID("00000000-68f9-1111-024e-222222111123"), - new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false); - } - - Console.WriteLine("SendInstantMessage: " + msg); - } - else - OutPacket(msg, ThrottleOutPacketType.Task); + OutPacket(msg, ThrottleOutPacketType.Task); } } @@ -2788,7 +2763,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Transfer.TransferInfo.Size = req.AssetInf.Data.Length; Transfer.TransferInfo.TransferID = req.TransferRequestID; Transfer.Header.Zerocoded = true; - OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); + OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset); if (req.NumPackets == 1) { @@ -2799,7 +2774,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Data = req.AssetInf.Data; TransferPacket.TransferData.Status = 1; TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset); } else { @@ -2832,7 +2807,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Status = 1; } TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset); processedLength += chunkSize; packetNumber++; @@ -3605,7 +3580,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - OutPacket(aw, ThrottleOutPacketType.Task); + OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); } public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index f1a181209a..e52ac37466 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Packets we have sent that need to be ACKed by the client public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); /// ACKs that are queued up, waiting to be sent to the client - public readonly OpenSim.Framework.LocklessQueue PendingAcks = new OpenSim.Framework.LocklessQueue(); + public readonly DoubleLocklessQueue PendingAcks = new DoubleLocklessQueue(); /// Current packet sequence number public int CurrentSequence; @@ -146,7 +146,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Throttle buckets for each packet category private readonly TokenBucket[] m_throttleCategories; /// Outgoing queues for throttled packets - private readonly OpenSim.Framework.LocklessQueue[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue[THROTTLE_CATEGORY_COUNT]; + private readonly DoubleLocklessQueue[] m_packetOutboxes = new DoubleLocklessQueue[THROTTLE_CATEGORY_COUNT]; /// A container that can hold one packet for each outbox, used to store /// dequeued packets that are being held for throttling private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; @@ -202,7 +202,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ThrottleOutPacketType type = (ThrottleOutPacketType)i; // Initialize the packet outboxes, where packets sit while they are waiting for tokens - m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + m_packetOutboxes[i] = new DoubleLocklessQueue(); // Initialize the token buckets that control the throttling for each category m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); } @@ -429,16 +429,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// false if the packet has not been queued and should be sent immediately. /// public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) + { + return EnqueueOutgoing(packet, forceQueue, false); + } + + public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority) { int category = (int)packet.Category; if (category >= 0 && category < m_packetOutboxes.Length) { - OpenSim.Framework.LocklessQueue queue = m_packetOutboxes[category]; + DoubleLocklessQueue queue = m_packetOutboxes[category]; if (m_deliverPackets == false) { - queue.Enqueue(packet); + queue.Enqueue(packet, highPriority); return true; } @@ -449,7 +454,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // queued packets if (queue.Count > 0) { - queue.Enqueue(packet); + queue.Enqueue(packet, highPriority); return true; } @@ -462,7 +467,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP else { // Force queue specified or not enough tokens in the bucket, queue this packet - queue.Enqueue(packet); + queue.Enqueue(packet, highPriority); return true; } } @@ -494,7 +499,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_deliverPackets == false) return false; OutgoingPacket packet = null; - OpenSim.Framework.LocklessQueue queue; + DoubleLocklessQueue queue; TokenBucket bucket; bool packetSent = false; ThrottleOutPacketTypeFlags emptyCategories = 0; @@ -534,7 +539,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } catch { - m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + m_packetOutboxes[i] = new DoubleLocklessQueue(); } if (success) { @@ -567,7 +572,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + m_packetOutboxes[i] = new DoubleLocklessQueue(); emptyCategories |= CategoryToFlag(i); } } @@ -724,4 +729,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } } + + public class DoubleLocklessQueue : OpenSim.Framework.LocklessQueue + { + OpenSim.Framework.LocklessQueue highQueue = new OpenSim.Framework.LocklessQueue(); + + public override int Count + { + get + { + return base.Count + highQueue.Count; + } + } + + public override bool Dequeue(out T item) + { + if (highQueue.Dequeue(out item)) + return true; + + return base.Dequeue(out item); + } + + public void Enqueue(T item, bool highPriority) + { + if (highPriority) + highQueue.Enqueue(item); + else + Enqueue(item); + } + } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 9a4abd4877..6c72edca08 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -803,6 +803,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Queue or Send + bool highPriority = false; + + if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) + { + category = (ThrottleOutPacketType)((int)category & 127); + highPriority = true; + } + OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); // If we were not provided a method for handling unacked, use the UDPServer default method outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); @@ -811,7 +819,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // continue to display the deleted object until relog. Therefore, we need to always queue a kill object // packet so that it isn't sent before a queued update packet. bool requestQueue = type == PacketType.KillObject; - if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) + if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) SendPacketFinal(outgoingPacket); #endregion Queue or Send diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 27cf20473a..7ec28605c1 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -373,6 +373,52 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { bool defonly = true; // are we only using default textures IImprovedAssetCache cache = m_scene.RequestModuleInterface(); + IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); + WearableCacheItem[] wearableCache = null; + + // Cache wearable data for teleport. + // Only makes sense if there's a bake module and a cache module + if (bakedModule != null && cache != null) + { + try + { + wearableCache = bakedModule.Get(sp.UUID); + } + catch (Exception) + { + + } + if (wearableCache != null) + { + for (int i = 0; i < wearableCache.Length; i++) + { + cache.Cache(wearableCache[i].TextureAsset); + } + } + } + /* + IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); + if (invService.GetRootFolder(userID) != null) + { + WearableCacheItem[] wearableCache = null; + if (bakedModule != null) + { + try + { + wearableCache = bakedModule.Get(userID); + appearance.WearableCacheItems = wearableCache; + appearance.WearableCacheItemsDirty = false; + foreach (WearableCacheItem item in wearableCache) + { + appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; + } + } + catch (Exception) + { + + } + } + */ // Process the texture entry for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) @@ -380,9 +426,32 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory int idx = AvatarAppearance.BAKE_INDICES[i]; Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; - // if there is no texture entry, skip it + // No face, so lets check our baked service cache, teleport or login. if (face == null) - continue; + { + if (wearableCache != null) + { + // If we find the an appearance item, set it as the textureentry and the face + WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); + if (searchitem != null) + { + sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); + sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; + face = sp.Appearance.Texture.FaceTextures[idx]; + } + else + { + // if there is no texture entry and no baked cache, skip it + continue; + } + } + else + { + //No texture entry face and no cache. Skip this face. + continue; + } + } + // m_log.DebugFormat( // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs deleted file mode 100644 index af54c1a1de..0000000000 --- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs +++ /dev/null @@ -1,257 +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.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -using Mono.Addins; - -namespace OpenSim.Region.CoreModules.Avatar.Groups -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")] - public class GroupsModule : ISharedRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Dictionary m_GroupMap = - new Dictionary(); - - private Dictionary m_ClientMap = - new Dictionary(); - - private UUID opensimulatorGroupID = - new UUID("00000000-68f9-1111-024e-222222111123"); - - private List m_SceneList = new List(); - - private static GroupMembershipData osGroup = - new GroupMembershipData(); - - private bool m_Enabled = false; - - #region ISharedRegionModule Members - - public void Initialise(IConfigSource config) - { - IConfig groupsConfig = config.Configs["Groups"]; - - if (groupsConfig == null) - { - m_log.Info("[GROUPS]: No configuration found. Using defaults"); - } - else - { - m_Enabled = groupsConfig.GetBoolean("Enabled", false); - if (!m_Enabled) - { - m_log.Info("[GROUPS]: Groups disabled in configuration"); - return; - } - - if (groupsConfig.GetString("Module", "Default") != "Default") - return; - } - - } - - public void AddRegion(Scene scene) - { - if (!m_Enabled) - return; - - lock (m_SceneList) - { - if (!m_SceneList.Contains(scene)) - { - if (m_SceneList.Count == 0) - { - osGroup.GroupID = opensimulatorGroupID; - osGroup.GroupName = "OpenSimulator Testing"; - osGroup.GroupPowers = - (uint)(GroupPowers.AllowLandmark | - GroupPowers.AllowSetHome); - m_GroupMap[opensimulatorGroupID] = osGroup; - } - m_SceneList.Add(scene); - } - } - - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnClientClosed += OnClientClosed; - // scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - } - - public void RemoveRegion(Scene scene) - { - if (!m_Enabled) - return; - - lock (m_SceneList) - { - if (m_SceneList.Contains(scene)) - m_SceneList.Remove(scene); - } - - scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnClientClosed -= OnClientClosed; - } - - public void RegionLoaded(Scene scene) - { - } - - public void PostInitialise() - { - } - - public void Close() - { - if (!m_Enabled) - return; - -// m_log.Debug("[GROUPS]: Shutting down group module."); - - lock (m_ClientMap) - { - m_ClientMap.Clear(); - } - - lock (m_GroupMap) - { - m_GroupMap.Clear(); - } - } - - public string Name - { - get { return "GroupsModule"; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - #endregion - - private void OnNewClient(IClientAPI client) - { - // Subscribe to instant messages -// client.OnInstantMessage += OnInstantMessage; - client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; - client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; - lock (m_ClientMap) - { - if (!m_ClientMap.ContainsKey(client.AgentId)) - { - m_ClientMap.Add(client.AgentId, client); - } - } - - GroupMembershipData[] updateGroups = new GroupMembershipData[1]; - updateGroups[0] = osGroup; - - client.SendGroupMembership(updateGroups); - } - - private void OnAgentDataUpdateRequest(IClientAPI remoteClient, - UUID AgentID, UUID SessionID) - { - UUID ActiveGroupID; - string ActiveGroupName; - ulong ActiveGroupPowers; - - string firstname = remoteClient.FirstName; - string lastname = remoteClient.LastName; - - string ActiveGroupTitle = "I IZ N0T"; - - ActiveGroupID = osGroup.GroupID; - ActiveGroupName = osGroup.GroupName; - ActiveGroupPowers = osGroup.GroupPowers; - - remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, - lastname, ActiveGroupPowers, ActiveGroupName, - ActiveGroupTitle); - } - -// private void OnInstantMessage(IClientAPI client, GridInstantMessage im) -// { -// } - -// private void OnGridInstantMessage(GridInstantMessage msg) -// { -// // Trigger the above event handler -// OnInstantMessage(null, msg); -// } - - private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) - { - string groupnamereply = "Unknown"; - UUID groupUUID = UUID.Zero; - - lock (m_GroupMap) - { - if (m_GroupMap.ContainsKey(id)) - { - GroupMembershipData grp = m_GroupMap[id]; - groupnamereply = grp.GroupName; - groupUUID = grp.GroupID; - } - } - remote_client.SendGroupNameReply(groupUUID, groupnamereply); - } - - private void OnClientClosed(UUID agentID, Scene scene) - { - lock (m_ClientMap) - { - if (m_ClientMap.ContainsKey(agentID)) - { -// IClientAPI cli = m_ClientMap[agentID]; -// if (cli != null) -// { -// //m_log.Info("[GROUPS]: Removing all reference to groups for " + cli.Name); -// } -// else -// { -// //m_log.Info("[GROUPS]: Removing all reference to groups for " + agentID.ToString()); -// } - m_ClientMap.Remove(agentID); - } - } - } - } -} diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 7e72d4747f..cb09047ad8 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -150,6 +150,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { client.OnTeleportHomeRequest += TriggerTeleportHome; client.OnTeleportLandmarkRequest += RequestTeleportLandmark; + client.OnTeleportCancel += TeleportCancel; } public virtual void Close() {} @@ -401,14 +402,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection // of whether the destination region completes the teleport. - if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", - sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); - - return; - } + m_entityTransferStateMachine.SetInTransit(sp.UUID); +// if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) +// { +// m_log.DebugFormat( +// "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", +// sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); +// +// return; +// } if (reg == null || finalDestination == null) { @@ -993,6 +995,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return neighbourRegion; } + private void TeleportCancel(IClientAPI remoteClient) + { + m_entityTransferStateMachine.ResetFromTransit(remoteClient.AgentId); + } + public bool Cross(ScenePresence agent, bool isFlying) { uint x; diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index a0ae2030cb..0276267be8 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -42,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using Mono.Addins; +using Amib.Threading; /***************************************************** * @@ -102,6 +103,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest private Dictionary m_pendingRequests; private Scene m_scene; // private Queue rpcQueue = new Queue(); + public static SmartThreadPool ThreadPool = null; public HttpRequestModule() { @@ -279,7 +281,30 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); + int maxThreads = 50; + + IConfig httpConfig = config.Configs["HttpRequestModule"]; + if (httpConfig != null) + { + maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); + } + m_pendingRequests = new Dictionary(); + + // First instance sets this up for all sims + if (ThreadPool == null) + { + STPStartInfo startInfo = new STPStartInfo(); + startInfo.IdleTimeout = 20000; + startInfo.MaxWorkerThreads = maxThreads; + startInfo.MinWorkerThreads = 5; + startInfo.ThreadPriority = ThreadPriority.BelowNormal; + startInfo.StartSuspended = true; + + ThreadPool = new SmartThreadPool(startInfo); + + ThreadPool.Start(); + } } public void AddRegion(Scene scene) @@ -340,7 +365,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest public string HttpMIMEType = "text/plain;charset=utf-8"; public int HttpTimeout; public bool HttpVerifyCert = true; - private Thread httpThread; + public IWorkItemResult WorkItem = null; // Request info private UUID _itemID; @@ -374,12 +399,16 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest public void Process() { - httpThread = new Thread(SendRequest); - httpThread.Name = "HttpRequestThread"; - httpThread.Priority = ThreadPriority.BelowNormal; - httpThread.IsBackground = true; _finished = false; - httpThread.Start(); + + lock (HttpRequestModule.ThreadPool) + WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); + } + + private object StpSendWrapper(object o) + { + SendRequest(); + return null; } /* @@ -409,13 +438,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { // We could hijack Connection Group Name to identify // a desired security exception. But at the moment we'll use a dummy header instead. -// Request.ConnectionGroupName = "NoVerify"; Request.Headers.Add("NoVerifyCert", "true"); } -// else -// { -// Request.ConnectionGroupName="Verify"; -// } if (proxyurl != null && proxyurl.Length > 0) { if (proxyexcepts != null && proxyexcepts.Length > 0) @@ -485,9 +509,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest ResponseBody = sb.ToString().Replace("\r", ""); } - catch (Exception e) + catch (WebException e) { - if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError) + if (e.Status == WebExceptionStatus.ProtocolError) { HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; Status = (int)webRsp.StatusCode; @@ -509,15 +533,25 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest ResponseBody = e.Message; } + if (ResponseBody == null) + ResponseBody = String.Empty; + _finished = true; return; } + catch (Exception e) + { + // Don't crash on anything else + } finally { if (response != null) response.Close(); } + if (ResponseBody == null) + ResponseBody = String.Empty; + _finished = true; } @@ -525,7 +559,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { try { - httpThread.Abort(); + if (!WorkItem.Cancel()) + { + WorkItem.Abort(); + } } catch (Exception) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 23006f2df6..e3bc8c7b36 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -282,7 +282,7 @@ namespace OpenSim.Region.Framework.Scenes private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing private volatile bool m_backingup; private Dictionary m_returns = new Dictionary(); - private Dictionary m_groupsWithTargets = new Dictionary(); + private Dictionary m_groupsWithTargets = new Dictionary(); private bool m_physics_enabled = true; private bool m_scripts_enabled = true; @@ -1736,7 +1736,7 @@ namespace OpenSim.Region.Framework.Scenes public void AddGroupTarget(SceneObjectGroup grp) { lock (m_groupsWithTargets) - m_groupsWithTargets[grp.UUID] = grp; + m_groupsWithTargets[grp.UUID] = 0; } public void RemoveGroupTarget(SceneObjectGroup grp) @@ -1747,18 +1747,24 @@ namespace OpenSim.Region.Framework.Scenes private void CheckAtTargets() { - List objs = null; + List objs = null; lock (m_groupsWithTargets) { if (m_groupsWithTargets.Count != 0) - objs = new List(m_groupsWithTargets.Values); + objs = new List(m_groupsWithTargets.Keys); } if (objs != null) { - foreach (SceneObjectGroup entry in objs) - entry.checkAtTargets(); + foreach (UUID entry in objs) + { + SceneObjectGroup grp = GetSceneObjectGroup(entry); + if (grp == null) + m_groupsWithTargets.Remove(entry); + else + grp.checkAtTargets(); + } } } @@ -2059,11 +2065,11 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerPrimsLoaded(this); } - public bool SuportsRayCastFiltered() + public bool SupportsRayCastFiltered() { if (PhysicsScene == null) return false; - return PhysicsScene.SuportsRaycastWorldFiltered(); + return PhysicsScene.SupportsRaycastWorldFiltered(); } public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index b4749796ec..ed1bbd8827 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -79,14 +79,14 @@ namespace OpenSim.Region.Framework.Scenes object_rez = 4194304 } - struct scriptPosTarget + public struct scriptPosTarget { public Vector3 targetPos; public float tolerance; public uint handle; } - struct scriptRotTarget + public struct scriptRotTarget { public Quaternion targetRot; public float tolerance; @@ -320,8 +320,18 @@ namespace OpenSim.Region.Framework.Scenes protected SceneObjectPart m_rootPart; // private Dictionary m_scriptEvents = new Dictionary(); - private Dictionary m_targets = new Dictionary(); - private Dictionary m_rotTargets = new Dictionary(); + private SortedDictionary m_targets = new SortedDictionary(); + private SortedDictionary m_rotTargets = new SortedDictionary(); + + public SortedDictionary AtTargets + { + get { return m_targets; } + } + + public SortedDictionary RotTargets + { + get { return m_rotTargets; } + } private bool m_scriptListens_atTarget; private bool m_scriptListens_notAtTarget; @@ -4112,6 +4122,8 @@ namespace OpenSim.Region.Framework.Scenes waypoint.handle = handle; lock (m_rotTargets) { + if (m_rotTargets.Count >= 8) + m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key); m_rotTargets.Add(handle, waypoint); } m_scene.AddGroupTarget(this); @@ -4137,6 +4149,8 @@ namespace OpenSim.Region.Framework.Scenes waypoint.handle = handle; lock (m_targets) { + if (m_targets.Count >= 8) + m_targets.Remove(m_targets.ElementAt(0).Key); m_targets.Add(handle, waypoint); } m_scene.AddGroupTarget(this); diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index d24ab2ac73..57e2d2045a 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -350,7 +350,7 @@ namespace OpenSim.Region.Physics.Manager return null; } - public virtual bool SuportsRaycastWorldFiltered() + public virtual bool SupportsRaycastWorldFiltered() { return false; } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index 51132104ad..510cbe90af 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -2643,7 +2643,7 @@ namespace OpenSim.Region.Physics.OdePlugin } } - public override bool SuportsRaycastWorldFiltered() + public override bool SupportsRaycastWorldFiltered() { return true; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 617f382242..53c6e5cf20 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3019,38 +3019,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGiveMoney(string destination, int amount) { - m_host.AddScriptLPS(1); - - if (m_item.PermsGranter == UUID.Zero) - return 0; - - if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) + Util.FireAndForget(x => { - LSLError("No permissions to give money"); - return 0; - } + m_host.AddScriptLPS(1); - UUID toID = new UUID(); + if (m_item.PermsGranter == UUID.Zero) + return; - if (!UUID.TryParse(destination, out toID)) - { - LSLError("Bad key in llGiveMoney"); - return 0; - } + if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) + { + LSLError("No permissions to give money"); + return; + } - IMoneyModule money = World.RequestModuleInterface(); + UUID toID = new UUID(); - if (money == null) - { - NotImplemented("llGiveMoney"); - return 0; - } + if (!UUID.TryParse(destination, out toID)) + { + LSLError("Bad key in llGiveMoney"); + return; + } - bool result = money.ObjectGiveMoney( - m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero); + IMoneyModule money = World.RequestModuleInterface(); - if (result) - return 1; + if (money == null) + { + NotImplemented("llGiveMoney"); + return; + } + + money.ObjectGiveMoney( + m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero); + }); return 0; } @@ -7322,7 +7322,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); - if (xmlrpcMod.IsEnabled()) + if (xmlrpcMod != null && xmlrpcMod.IsEnabled()) { UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface(); @@ -7354,6 +7354,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); ScriptSleep(3000); + if (xmlrpcMod == null) + return ""; return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); } @@ -7361,7 +7363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); - xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); + if (xmlrpcMod != null) + xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); ScriptSleep(3000); } @@ -7369,7 +7372,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); - xmlrpcMod.CloseXMLRPCChannel((UUID)channel); + if (xmlrpcMod != null) + xmlrpcMod.CloseXMLRPCChannel((UUID)channel); ScriptSleep(1000); } @@ -7782,8 +7786,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); - - ScriptSleep(200); } private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) @@ -12209,7 +12211,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); - if (World.SuportsRayCastFiltered()) + if (World.SupportsRayCastFiltered()) { if (dist == 0) return list; @@ -12272,13 +12274,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - if (checkTerrain) - { - ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); - if (groundContact != null) - results.Add((ContactResult)groundContact); - } - if (checkAgents) { ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); @@ -12294,6 +12289,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + // Double check this + if (checkTerrain) + { + bool skipGroundCheck = false; + + foreach (ContactResult c in results) + { + if (c.ConsumerID == 0) // Physics gave us a ground collision + skipGroundCheck = true; + } + + if (!skipGroundCheck) + { + ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); + if (groundContact != null) + results.Add((ContactResult)groundContact); + } + } + results.Sort(delegate(ContactResult a, ContactResult b) { return a.Depth.CompareTo(b.Depth); @@ -12587,7 +12601,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } bool result = money.ObjectGiveMoney( - m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero); + m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn); if (result) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 51c8c7ed89..7c2f8edbca 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1821,17 +1821,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { UUID assetID = UUID.Zero; - if (!UUID.TryParse(notecardNameOrUuid, out assetID)) + bool notecardNameIsUUID = UUID.TryParse(notecardNameOrUuid, out assetID); + + if (!notecardNameIsUUID) { - m_host.TaskInventory.LockItemsForRead(true); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) - { - if (item.Type == 7 && item.Name == notecardNameOrUuid) - { - assetID = item.AssetID; - } - } - m_host.TaskInventory.LockItemsForRead(false); + assetID = SearchTaskInventoryForAssetId(notecardNameOrUuid); } if (assetID == UUID.Zero) @@ -1842,7 +1836,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api AssetBase a = World.AssetService.Get(assetID.ToString()); if (a == null) - return UUID.Zero; + { + // Whoops, it's still possible here that the notecard name was properly + // formatted like a UUID but isn't an asset UUID so lets look it up by name after all + assetID = SearchTaskInventoryForAssetId(notecardNameOrUuid); + if (assetID == UUID.Zero) + return UUID.Zero; + + if (!NotecardCache.IsCached(assetID)) + { + a = World.AssetService.Get(assetID.ToString()); + + if (a == null) + { + return UUID.Zero; + } + } + } string data = Encoding.UTF8.GetString(a.Data); NotecardCache.Cache(assetID, data); @@ -1850,6 +1860,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return assetID; } + protected UUID SearchTaskInventoryForAssetId(string name) + { + UUID assetId = UUID.Zero; + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 7 && item.Name == name) + { + assetId = item.AssetID; + } + } + m_host.TaskInventory.LockItemsForRead(false); + return assetId; + } /// /// Directly get an entire notecard at once. diff --git a/prebuild.xml b/prebuild.xml index 7fff2e04d3..fa2172268c 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1680,6 +1680,7 @@ +