diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index c5d9641da7..16385417e6 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -358,6 +358,9 @@ namespace OpenSim.Framework SetVisualParams(visualParams); } + /// + /// Set avatar height by a calculation based on their visual parameters. + /// public virtual void SetHeight() { // Start with shortest possible female avatar height diff --git a/OpenSim/Framework/Client/IClientChat.cs b/OpenSim/Framework/Client/IClientChat.cs index 078ea9b668..86b1faa8f6 100644 --- a/OpenSim/Framework/Client/IClientChat.cs +++ b/OpenSim/Framework/Client/IClientChat.cs @@ -33,7 +33,8 @@ namespace OpenSim.Framework.Client { event ChatMessage OnChatFromClient; - void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, - byte audible); + void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, + byte audible); } -} +} \ No newline at end of file diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs index a7cf0c03b2..16a63e0ca5 100644 --- a/OpenSim/Framework/Console/ConsoleUtil.cs +++ b/OpenSim/Framework/Console/ConsoleUtil.cs @@ -27,88 +27,202 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using log4net; using OpenMetaverse; -public class ConsoleUtil +namespace OpenSim.Framework.Console { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public const string MinRawConsoleVectorValue = "-~"; - public const string MaxRawConsoleVectorValue = "~"; - - public const string VectorSeparator = ","; - public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); - - /// - /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 - /// - /// /param> - /// - /// - public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) + public class ConsoleUtil { - return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); - } + // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 - /// - /// /param> - /// - /// - public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) - { - return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); - } + public const int LocalIdNotFound = 0; + + /// + /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section + /// rather than in each help summary. + /// + public const string CoordHelp + = @"Each component of the coord is comma separated. There must be no spaces between the commas. + If you don't care about the z component you can simply omit it. + If you don't care about the x or y components then you can leave them blank (though a comma is still required) + If you want to specify the maxmimum value of a component then you can use ~ instead of a number + If you want to specify the minimum value of a component then you can use -~ instead of a number + e.g. + delete object pos 20,20,20 to 40,40,40 + delete object pos 20,20 to 40,40 + delete object pos ,20,20 to ,40,40 + delete object pos ,,30 to ,,~ + delete object pos ,,-~ to ,,30"; + + public const string MinRawConsoleVectorValue = "-~"; + public const string MaxRawConsoleVectorValue = "~"; + + public const string VectorSeparator = ","; + public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); - /// - /// Convert a vector input from the console to an OpenMetaverse.Vector3 - /// - /// - /// A string in the form ,, where there is no space between values. - /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value - /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) - /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue - /// Other than that, component values must be numeric. - /// - /// - /// - /// - public static bool TryParseConsoleVector( - string rawConsoleVector, Func blankComponentFunc, out Vector3 vector) - { - List components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); - - if (components.Count < 1 || components.Count > 3) + /// + /// Check if the given file path exists. + /// + /// If not, warning is printed to the given console. + /// true if the file does not exist, false otherwise. + /// + /// + public static bool CheckFileDoesNotExist(ICommandConsole console, string path) { - vector = Vector3.Zero; - return false; + if (File.Exists(path)) + { + console.OutputFormat("File {0} already exists. Please move or remove it.", path); + return false; + } + + return true; + } + + /// + /// Try to parse a console UUID from the console. + /// + /// + /// Will complain to the console if parsing fails. + /// + /// + /// If null then no complaint is printed. + /// + /// + public static bool TryParseConsoleUuid(ICommandConsole console, string rawUuid, out UUID uuid) + { + if (!UUID.TryParse(rawUuid, out uuid)) + { + if (console != null) + console.OutputFormat("{0} is not a valid uuid", rawUuid); + + return false; + } + + return true; } - for (int i = components.Count; i < 3; i++) - components.Add(""); + public static bool TryParseConsoleLocalId(ICommandConsole console, string rawLocalId, out uint localId) + { + if (!uint.TryParse(rawLocalId, out localId)) + { + if (console != null) + console.OutputFormat("{0} is not a valid local id", localId); - List semiDigestedComponents - = components.ConvertAll( - c => - { - if (c == "") - return blankComponentFunc.Invoke(c); - else if (c == MaxRawConsoleVectorValue) - return float.MaxValue.ToString(); - else if (c == MinRawConsoleVectorValue) - return float.MinValue.ToString(); - else - return c; - }); + return false; + } - string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); + if (localId == 0) + { + if (console != null) + console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId); -// m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); + return false; + } - return Vector3.TryParse(semiDigestedConsoleVector, out vector); + return true; + } + + /// + /// Tries to parse the input as either a UUID or a local ID. + /// + /// true if parsing succeeded, false otherwise. + /// + /// + /// + /// + /// Will be set to ConsoleUtil.LocalIdNotFound if parsing result was a UUID or no parse succeeded. + /// + public static bool TryParseConsoleId(ICommandConsole console, string rawId, out UUID uuid, out uint localId) + { + if (TryParseConsoleUuid(null, rawId, out uuid)) + { + localId = LocalIdNotFound; + return true; + } + + if (TryParseConsoleLocalId(null, rawId, out localId)) + { + return true; + } + + if (console != null) + console.OutputFormat("{0} is not a valid UUID or local id", rawId); + + return false; + } + + /// + /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 + /// + /// /param> + /// + /// + public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) + { + return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); + } + + /// + /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 + /// + /// /param> + /// + /// + public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) + { + return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); + } + + /// + /// Convert a vector input from the console to an OpenMetaverse.Vector3 + /// + /// + /// A string in the form ,, where there is no space between values. + /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value + /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) + /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue + /// Other than that, component values must be numeric. + /// + /// + /// + /// + public static bool TryParseConsoleVector( + string rawConsoleVector, Func blankComponentFunc, out Vector3 vector) + { + List components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); + + if (components.Count < 1 || components.Count > 3) + { + vector = Vector3.Zero; + return false; + } + + for (int i = components.Count; i < 3; i++) + components.Add(""); + + List semiDigestedComponents + = components.ConvertAll( + c => + { + if (c == "") + return blankComponentFunc.Invoke(c); + else if (c == MaxRawConsoleVectorValue) + return float.MaxValue.ToString(); + else if (c == MinRawConsoleVectorValue) + return float.MinValue.ToString(); + else + return c; + }); + + string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); + + // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); + + return Vector3.TryParse(semiDigestedConsoleVector, out vector); + } } } \ No newline at end of file diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index e95149da63..a1df6378e8 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1112,8 +1112,20 @@ namespace OpenSim.Framework void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); - void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, - byte audible); + /// + /// Send chat to the viewer. + /// + /// + /// + /// + /// + /// + /// + /// + /// + void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, + byte audible); void SendInstantMessage(GridInstantMessage im); diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index b410a0ea90..7232383a77 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -621,7 +621,7 @@ namespace OpenSim if (account == null) { m_log.ErrorFormat( - "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first."); + "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level."); } else { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 67ce48e243..3c65647dc4 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -846,8 +846,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(mov, ThrottleOutPacketType.Unknown); } - public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); reply.ChatData.Audible = audible; @@ -856,7 +857,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.ChatData.SourceType = source; reply.ChatData.Position = fromPos; reply.ChatData.FromName = Util.StringToBytes256(fromName); - reply.ChatData.OwnerID = fromAgentID; + reply.ChatData.OwnerID = ownerID; reply.ChatData.SourceID = fromAgentID; OutPacket(reply, ThrottleOutPacketType.Unknown); diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index dbbb0aec7d..4407e40392 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -197,6 +197,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat string fromName = c.From; string fromNamePrefix = ""; UUID fromID = UUID.Zero; + UUID ownerID = UUID.Zero; string message = c.Message; IScene scene = c.Scene; UUID destination = c.Destination; @@ -224,11 +225,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromNamePrefix = m_adminPrefix; } destination = UUID.Zero; // Avatars cant "SayTo" + ownerID = c.Sender.AgentId; + break; case ChatSourceType.Object: fromID = c.SenderUUID; + if (c.SenderObject != null && c.SenderObject is SceneObjectPart) + ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; + break; } @@ -262,8 +268,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat // objects on a parcel with access restrictions if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) { - if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType)) - receiverIDs.Add(presence.UUID); + if (destination != UUID.Zero) + { + if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true)) + receiverIDs.Add(presence.UUID); + } + else + { + if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false)) + receiverIDs.Add(presence.UUID); + } } } } @@ -324,7 +338,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) return; - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, + client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, (byte)sourceType, (byte)ChatAudibleLevel.Fully); receiverIDs.Add(client.AgentId); } @@ -341,15 +355,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat /// /// /param> /// + /// + /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID. + /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762 + /// /// /// /// /// /// true if the message was sent to the receiver, false if it was not sent due to failing a /// precondition - protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, - UUID fromAgentID, string fromName, ChatTypeEnum type, - string message, ChatSourceType src) + protected virtual bool TrySendChatMessage( + ScenePresence presence, Vector3 fromPos, Vector3 regionPos, + UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, + string message, ChatSourceType src, bool ignoreDistance) { // don't send chat to child agents if (presence.IsChildAgent) return false; @@ -369,8 +388,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } // TODO: should change so the message is sent through the avatar rather than direct to the ClientView - presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, - fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); + presence.ControllingClient.SendChatMessage( + message, (byte) type, fromPos, fromName, + fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); return true; } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 7d1fe68e8c..a32afd566f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -35,6 +35,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; +using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -209,6 +210,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver Guid id, string firstName, string lastName, string invPath, string pass, string savePath, Dictionary options) { + if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) + return false; + if (m_scenes.Count > 0) { UserAccount userInfo = GetUserInfo(firstName, lastName, pass); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 21dff4bfee..ecaab4476b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -38,15 +38,15 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { - public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule + public class InventoryTransferModule : ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// private List m_Scenelist = new List(); - private Dictionary m_AgentRegions = - new Dictionary(); +// private Dictionary m_AgentRegions = +// new Dictionary(); private IMessageTransferModule m_TransferModule = null; private bool m_Enabled = true; @@ -76,12 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Add(scene); - scene.RegisterModuleInterface(this); +// scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnClientClosed += ClientLoggedOut; +// scene.EventManager.OnClientClosed += ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; +// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; } public void RegionLoaded(Scene scene) @@ -96,9 +96,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Clear(); scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnClientClosed -= ClientLoggedOut; +// scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; +// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; } } } @@ -106,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer public void RemoveRegion(Scene scene) { scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnClientClosed -= ClientLoggedOut; +// scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; +// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; m_Scenelist.Remove(scene); } @@ -138,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.OnInstantMessage += OnInstantMessage; } - protected void OnSetRootAgentScene(UUID id, Scene scene) - { - m_AgentRegions[id] = scene; - } +// protected void OnSetRootAgentScene(UUID id, Scene scene) +// { +// m_AgentRegions[id] = scene; +// } private Scene FindClientScene(UUID agentId) { @@ -465,69 +465,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer } } - public bool NeedSceneCacheClear(UUID agentID, Scene scene) - { - if (!m_AgentRegions.ContainsKey(agentID)) - { - // Since we can get here two ways, we need to scan - // the scenes here. This is somewhat more expensive - // but helps avoid a nasty bug - // - - foreach (Scene s in m_Scenelist) - { - ScenePresence presence; - - if (s.TryGetScenePresence(agentID, out presence)) - { - // If the agent is in this scene, then we - // are being called twice in a single - // teleport. This is wasteful of cycles - // but harmless due to this 2nd level check - // - // If the agent is found in another scene - // then the list wasn't current - // - // If the agent is totally unknown, then what - // are we even doing here?? - // - if (s == scene) - { - //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); - return true; - } - else - { - //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); - return false; - } - } - } - //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); - return true; - } - - // The agent is left in current Scene, so we must be - // going to another instance - // - if (m_AgentRegions[agentID] == scene) - { - //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); - m_AgentRegions.Remove(agentID); - return true; - } - - // Another region has claimed the agent - // - //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); - return false; - } - - public void ClientLoggedOut(UUID agentID, Scene scene) - { - if (m_AgentRegions.ContainsKey(agentID)) - m_AgentRegions.Remove(agentID); - } +// public bool NeedSceneCacheClear(UUID agentID, Scene scene) +// { +// if (!m_AgentRegions.ContainsKey(agentID)) +// { +// // Since we can get here two ways, we need to scan +// // the scenes here. This is somewhat more expensive +// // but helps avoid a nasty bug +// // +// +// foreach (Scene s in m_Scenelist) +// { +// ScenePresence presence; +// +// if (s.TryGetScenePresence(agentID, out presence)) +// { +// // If the agent is in this scene, then we +// // are being called twice in a single +// // teleport. This is wasteful of cycles +// // but harmless due to this 2nd level check +// // +// // If the agent is found in another scene +// // then the list wasn't current +// // +// // If the agent is totally unknown, then what +// // are we even doing here?? +// // +// if (s == scene) +// { +// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); +// return true; +// } +// else +// { +// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); +// return false; +// } +// } +// } +// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); +// return true; +// } +// +// // The agent is left in current Scene, so we must be +// // going to another instance +// // +// if (m_AgentRegions[agentID] == scene) +// { +// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); +// m_AgentRegions.Remove(agentID); +// return true; +// } +// +// // Another region has claimed the agent +// // +// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); +// return false; +// } +// +// public void ClientLoggedOut(UUID agentID, Scene scene) +// { +// if (m_AgentRegions.ContainsKey(agentID)) +// m_AgentRegions.Remove(agentID); +// } /// /// diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ffc362ff70..31e6ce9719 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -677,13 +677,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Reset(); } - // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! - if (sp.Scene.NeedSceneCacheClear(sp.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", - sp.UUID); - } + // Commented pending deletion since this method no longer appears to do anything at all +// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! +// if (sp.Scene.NeedSceneCacheClear(sp.UUID)) +// { +// m_log.DebugFormat( +// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", +// sp.UUID); +// } m_entityTransferStateMachine.ResetFromTransit(sp.UUID); } @@ -1222,11 +1223,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // the user may change their profile information in other region, // so the userinfo in UserProfileCache is not reliable any more, delete it // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! - if (agent.Scene.NeedSceneCacheClear(agent.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); - } +// if (agent.Scene.NeedSceneCacheClear(agent.UUID)) +// { +// m_log.DebugFormat( +// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); +// } //m_log.Debug("AFTER CROSS"); //Scene.DumpChildrenSeeds(UUID); diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 07bb291241..e167e312da 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Text.RegularExpressions; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -172,12 +173,42 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm /// UUID of the SceneObjectPart /// channel to listen on /// name to filter on - /// key to filter on (user given, could be totally faked) + /// + /// key to filter on (user given, could be totally faked) + /// /// msg to filter on /// number of the scripts handle - public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) + public int Listen(uint localID, UUID itemID, UUID hostID, int channel, + string name, UUID id, string msg) { - return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); + return m_listenerManager.AddListener(localID, itemID, hostID, + channel, name, id, msg); + } + + /// + /// Create a listen event callback with the specified filters. + /// The parameters localID,itemID are needed to uniquely identify + /// the script during 'peek' time. Parameter hostID is needed to + /// determine the position of the script. + /// + /// localID of the script engine + /// UUID of the script engine + /// UUID of the SceneObjectPart + /// channel to listen on + /// name to filter on + /// + /// key to filter on (user given, could be totally faked) + /// + /// msg to filter on + /// + /// Bitfield indicating which strings should be processed as regex. + /// + /// number of the scripts handle + public int Listen(uint localID, UUID itemID, UUID hostID, int channel, + string name, UUID id, string msg, int regexBitfield) + { + return m_listenerManager.AddListener(localID, itemID, hostID, + channel, name, id, msg, regexBitfield); } /// @@ -326,7 +357,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (channel == 0) { // Channel 0 goes to viewer ONLY - m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); + m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); return true; } @@ -470,15 +501,25 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_curlisteners = 0; } - public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) + public int AddListener(uint localID, UUID itemID, UUID hostID, + int channel, string name, UUID id, string msg) + { + return AddListener(localID, itemID, hostID, channel, name, id, + msg, 0); + } + + public int AddListener(uint localID, UUID itemID, UUID hostID, + int channel, string name, UUID id, string msg, + int regexBitfield) { // do we already have a match on this particular filter event? - List coll = GetListeners(itemID, channel, name, id, msg); + List coll = GetListeners(itemID, channel, name, id, + msg); if (coll.Count > 0) { - // special case, called with same filter settings, return same handle - // (2008-05-02, tested on 1.21.1 server, still holds) + // special case, called with same filter settings, return same + // handle (2008-05-02, tested on 1.21.1 server, still holds) return coll[0].GetHandle(); } @@ -490,7 +531,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (newHandle > 0) { - ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); + ListenerInfo li = new ListenerInfo(newHandle, localID, + itemID, hostID, channel, name, id, msg, + regexBitfield); List listeners; if (!m_listeners.TryGetValue(channel,out listeners)) @@ -631,6 +674,22 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm return -1; } + /// These are duplicated from ScriptBaseClass + /// http://opensimulator.org/mantis/view.php?id=6106#c21945 + #region Constants for the bitfield parameter of osListenRegex + + /// + /// process name parameter as regex + /// + public const int OS_LISTEN_REGEX_NAME = 0x1; + + /// + /// process message parameter as regex + /// + public const int OS_LISTEN_REGEX_MESSAGE = 0x2; + + #endregion + // Theres probably a more clever and efficient way to // do this, maybe with regex. // PM2008: Ha, one could even be smart and define a specialized Enumerator. @@ -656,7 +715,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetName().Length > 0 && !li.GetName().Equals(name)) + if (li.GetName().Length > 0 && ( + ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || + ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) + )) { continue; } @@ -664,7 +726,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) + if (li.GetMessage().Length > 0 && ( + ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || + ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) + )) { continue; } @@ -697,10 +762,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { int idx = 0; Object[] item = new Object[6]; + int dataItemLength = 6; while (idx < data.Length) { - Array.Copy(data, idx, item, 0, 6); + dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; + item = new Object[dataItemLength]; + Array.Copy(data, idx, item, 0, dataItemLength); ListenerInfo info = ListenerInfo.FromData(localID, itemID, hostID, item); @@ -712,12 +780,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_listeners[(int)item[2]].Add(info); } - idx+=6; + idx+=dataItemLength; } } } - public class ListenerInfo: IWorldCommListenerInfo + public class ListenerInfo : IWorldCommListenerInfo { private bool m_active; // Listener is active or not private int m_handle; // Assigned handle of this listener @@ -731,16 +799,29 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) { - Initialise(handle, localID, ItemID, hostID, channel, name, id, message); + Initialise(handle, localID, ItemID, hostID, channel, name, id, + message, 0); + } + + public ListenerInfo(int handle, uint localID, UUID ItemID, + UUID hostID, int channel, string name, UUID id, + string message, int regexBitfield) + { + Initialise(handle, localID, ItemID, hostID, channel, name, id, + message, regexBitfield); } public ListenerInfo(ListenerInfo li, string name, UUID id, string message) { - Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); + Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0); } - private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, - UUID id, string message) + public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield) + { + Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield); + } + + private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield) { m_active = true; m_handle = handle; @@ -751,11 +832,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_name = name; m_id = id; m_message = message; + RegexBitfield = regexBitfield; } public Object[] GetSerializationData() { - Object[] data = new Object[6]; + Object[] data = new Object[7]; data[0] = m_active; data[1] = m_handle; @@ -763,16 +845,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm data[3] = m_name; data[4] = m_id; data[5] = m_message; + data[6] = RegexBitfield; return data; } public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) { - ListenerInfo linfo = new ListenerInfo((int)data[1], localID, - ItemID, hostID, (int)data[2], (string)data[3], - (UUID)data[4], (string)data[5]); - linfo.m_active=(bool)data[0]; + ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]); + linfo.m_active = (bool)data[0]; + if (data.Length >= 7) + { + linfo.RegexBitfield = (int)data[6]; + } return linfo; } @@ -831,5 +916,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { return m_id; } + + public int RegexBitfield { get; private set; } } } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs index a66ed88ad1..d8dace20c8 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs @@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX; } - Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastY - firstY + 1), (int)(lastX - firstX + 1)); + Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1)); // Calculate the subdirectory in which each region will be stored in the archive diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 2a87dc2a5f..970487a3d4 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -32,6 +32,8 @@ using System.Reflection; using log4net; using NDesk.Options; using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -117,7 +119,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // // foreach (string param in mainParams) // m_log.DebugFormat("GOT PARAM [{0}]", param); - + if (mainParams.Count > 2) { DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); @@ -150,14 +152,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver List mainParams = ops.Parse(cmdparams); + string path; if (mainParams.Count > 2) - { - ArchiveRegion(mainParams[2], options); - } + path = mainParams[2]; else - { - ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options); - } + path = DEFAULT_OAR_BACKUP_FILENAME; + + if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path)) + return; + + ArchiveRegion(path, options); } public void ArchiveRegion(string savePath, Dictionary options) diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 87241e1559..b2c9bce7e5 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -27,10 +27,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using System.Xml; using log4net; using Mono.Addins; using NDesk.Options; @@ -41,6 +43,7 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; namespace OpenSim.Region.CoreModules.World.Objects.Commands { @@ -96,9 +99,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands HandleDeleteObject); m_console.Commands.AddCommand( - "Objects", false, "delete object uuid", - "delete object uuid ", - "Delete a scene object by uuid", + "Objects", false, "delete object id", + "delete object id ", + "Delete a scene object by uuid or localID", HandleDeleteObject); m_console.Commands.AddCommand( @@ -122,28 +125,18 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "delete object pos", "delete object pos to ", "Delete scene objects within the given area.", - "Each component of the coord is comma separated. There must be no spaces between the commas.\n" - + "If you don't care about the z component you can simply omit it.\n" - + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" - + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" - + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" - + "e.g.\n" - + "delete object pos 20,20,20 to 40,40,40\n" - + "delete object pos 20,20 to 40,40\n" - + "delete object pos ,20,20 to ,40,40\n" - + "delete object pos ,,30 to ,,~\n" - + "delete object pos ,,-~ to ,,30", + ConsoleUtil.CoordHelp, HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, - "show object uuid", - "show object uuid [--full] ", - "Show details of a scene object with the given UUID", + "show object id", + "show object id [--full] ", + "Show details of a scene object with the given UUID or localID", "The --full option will print out information on all the parts of the object.\n" + "For yet more detailed part information, use the \"show part\" commands.", - HandleShowObjectByUuid); + HandleShowObjectById); m_console.Commands.AddCommand( "Objects", @@ -164,25 +157,15 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Show details of scene objects within the given area.", "The --full option will print out information on all the parts of the object.\n" + "For yet more detailed part information, use the \"show part\" commands.\n" - + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" - + "If you don't care about the z component you can simply omit it.\n" - + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" - + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" - + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" - + "e.g.\n" - + "show object pos 20,20,20 to 40,40,40\n" - + "show object pos 20,20 to 40,40\n" - + "show object pos ,20,20 to ,40,40\n" - + "show object pos ,,30 to ,,~\n" - + "show object pos ,,-~ to ,,30", + + ConsoleUtil.CoordHelp, HandleShowObjectByPos); m_console.Commands.AddCommand( "Objects", false, - "show part uuid", - "show part uuid ", - "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); + "show part id", + "show part id ", + "Show details of a scene object part with the given UUID or localID", HandleShowPartById); m_console.Commands.AddCommand( "Objects", @@ -190,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show part name", "show part name [--regex] ", "Show details of scene object parts with the given name.", - "If --regex is specified then the name is treatead as a regular expression", + "If --regex is specified then the name is treated as a regular expression", HandleShowPartByName); m_console.Commands.AddCommand( @@ -199,18 +182,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show part pos", "show part pos to ", "Show details of scene object parts within the given area.", - "Each component of the coord is comma separated. There must be no spaces between the commas.\n" - + "If you don't care about the z component you can simply omit it.\n" - + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" - + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" - + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" - + "e.g.\n" - + "show object pos 20,20,20 to 40,40,40\n" - + "show object pos 20,20 to 40,40\n" - + "show object pos ,20,20 to ,40,40\n" - + "show object pos ,,30 to ,,~\n" - + "show object pos ,,-~ to ,,30", + ConsoleUtil.CoordHelp, HandleShowPartByPos); + + m_console.Commands.AddCommand( + "Objects", + false, + "dump object id", + "dump object id ", + "Dump the formatted serialization of the given object to the file .xml", + "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" + + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n" + + "If a local ID is given then the filename used is still that for the UUID", + HandleDumpObjectById); } public void RemoveRegion(Scene scene) @@ -265,7 +249,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void HandleShowObjectByUuid(string module, string[] cmdparams) + private void HandleShowObjectById(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; @@ -281,14 +265,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - UUID objectUuid; - if (!UUID.TryParse(mainParams[3], out objectUuid)) - { - m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); + UUID uuid; + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) return; - } - SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); + SceneObjectGroup so; + + if (localId != ConsoleUtil.LocalIdNotFound) + so = m_scene.GetSceneObjectGroup(localId); + else + so = m_scene.GetSceneObjectGroup(uuid); if (so == null) { @@ -365,7 +352,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSogsToConsole(searchPredicate, showFull); } - private void HandleShowPartByUuid(string module, string[] cmdparams) + private void HandleShowPartById(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; @@ -378,18 +365,20 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part uuid [--full] "); + m_console.OutputFormat("Usage: show part id [--full] "); return; } UUID objectUuid; - if (!UUID.TryParse(mainParams[3], out objectUuid)) - { - m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) return; - } - SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); + SceneObjectPart sop; + if (localId == ConsoleUtil.LocalIdNotFound) + sop = m_scene.GetSceneObjectPart(objectUuid); + else + sop = m_scene.GetSceneObjectPart(localId); if (sop == null) { @@ -477,6 +466,51 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSopsToConsole(searchPredicate, true); } + private void HandleDumpObjectById(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmdparams.Length < 4) + { + m_console.OutputFormat("Usage: dump object id "); + return; + } + + UUID objectUuid; + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId)) + return; + + SceneObjectGroup so; + if (localId == ConsoleUtil.LocalIdNotFound) + so = m_scene.GetSceneObjectGroup(objectUuid); + else + so = m_scene.GetSceneObjectGroup(localId); + + if (so == null) + { +// m_console.OutputFormat("No part found with uuid {0}", objectUuid); + return; + } + + // In case we found it via local ID. + objectUuid = so.UUID; + + string fileName = string.Format("{0}.xml", objectUuid); + + if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) + return; + + using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) + { + xtw.Formatting = Formatting.Indented; + SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); + } + + m_console.OutputFormat("Object dumped to file {0}", fileName); + } + /// /// Append a scene object report to an input StringBuilder /// @@ -641,19 +675,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; - case "uuid": - if (!UUID.TryParse(o, out match)) + case "id": + UUID uuid; + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId)) return; requireConfirmation = false; deletes = new List(); - - m_scene.ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.UUID == match && !g.IsAttachment) - deletes.Add(g); - }); - + + SceneObjectGroup so; + if (localId == ConsoleUtil.LocalIdNotFound) + so = m_scene.GetSceneObjectGroup(uuid); + else + so = m_scene.GetSceneObjectGroup(localId); + + if (!so.IsAttachment) + deletes.Add(so); + // if (deletes.Count == 0) // m_console.OutputFormat("No objects were found with uuid {0}", match); diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index e8e375e037..20e0199d7b 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs @@ -45,6 +45,13 @@ namespace OpenSim.Region.Framework.Interfaces void Deactivate(); void Activate(); UUID GetID(); + + /// + /// Bitfield indicating which strings should be processed as regex. + /// 1 corresponds to IWorldCommListenerInfo::GetName() + /// 2 corresponds to IWorldCommListenerInfo::GetMessage() + /// + int RegexBitfield { get; } } public interface IWorldComm @@ -60,7 +67,7 @@ namespace OpenSim.Region.Framework.Interfaces /// the script during 'peek' time. Parameter hostID is needed to /// determine the position of the script. /// - /// localID of the script engine + /// localID of the script engine /// UUID of the script engine /// UUID of the SceneObjectPart /// channel to listen on @@ -70,6 +77,23 @@ namespace OpenSim.Region.Framework.Interfaces /// number of the scripts handle int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); + /// + /// Create a listen event callback with the specified filters. + /// The parameters localID,itemID are needed to uniquely identify + /// the script during 'peek' time. Parameter hostID is needed to + /// determine the position of the script. + /// + /// localID of the script engine + /// UUID of the script engine + /// UUID of the SceneObjectPart + /// channel to listen on + /// name to filter on + /// key to filter on (user given, could be totally faked) + /// msg to filter on + /// Bitfield indicating which strings should be processed as regex. + /// number of the scripts handle + int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield); + /// /// This method scans over the objects which registered an interest in listen callbacks. /// For everyone it finds, it checks if it fits the given filter. If it does, then diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index ad421eeedb..9ed4f47743 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation { if (m_defaultAnimation.AnimID == animID) { - m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero); + m_defaultAnimation = new OpenSim.Framework.Animation(animID, 1, UUID.Zero); } else if (HasAnimation(animID)) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 16c0d25752..ce6415a8b9 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -38,8 +38,20 @@ namespace OpenSim.Region.Framework.Scenes { public partial class Scene { + /// + /// Send chat to listeners. + /// + /// + /// /param> + /// + /// + /// + /// + /// + /// + /// public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, - UUID fromID, bool fromAgent, bool broadcast, UUID destination) + UUID fromID, UUID targetID, bool fromAgent, bool broadcast) { OSChatMessage args = new OSChatMessage(); @@ -49,7 +61,7 @@ namespace OpenSim.Region.Framework.Scenes args.Position = fromPos; args.SenderUUID = fromID; args.Scene = this; - args.Destination = destination; + args.Destination = targetID; if (fromAgent) { @@ -66,6 +78,10 @@ namespace OpenSim.Region.Framework.Scenes args.From = fromName; //args. +// m_log.DebugFormat( +// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", +// args.Message.Replace("\n", "\\n"), args.Channel, args.Type, fromName, broadcast); + if (broadcast) EventManager.TriggerOnChatBroadcast(this, args); else @@ -75,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent, bool broadcast) { - SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero); + SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast); } /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 45d512b7f0..218d4e4002 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1300,6 +1300,12 @@ namespace OpenSim.Region.Framework.Scenes // This is the method that shuts down the scene. public override void Close() { + if (m_shuttingDown) + { + m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); + return; + } + m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); StatsReporter.Close(); @@ -1343,6 +1349,14 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGraph.Close(); + if (!GridService.DeregisterRegion(RegionInfo.RegionID)) + m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); + + base.Close(); + + // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. + // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can + // attempt to reference a null or disposed physics scene. if (PhysicsScene != null) { PhysicsScene phys = PhysicsScene; @@ -1351,12 +1365,6 @@ namespace OpenSim.Region.Framework.Scenes phys.Dispose(); phys = null; } - - if (!GridService.DeregisterRegion(RegionInfo.RegionID)) - m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); - - // call the base class Close method. - base.Close(); } /// @@ -3595,9 +3603,10 @@ namespace OpenSim.Region.Framework.Scenes if (closeChildAgents && CapsModule != null) CapsModule.RemoveCaps(agentID); - // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever - // this method is doing is HORRIBLE!!! - avatar.Scene.NeedSceneCacheClear(avatar.UUID); +// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever +// // this method is doing is HORRIBLE!!! + // Commented pending deletion since this method no longer appears to do anything at all +// avatar.Scene.NeedSceneCacheClear(avatar.UUID); if (closeChildAgents && !isChildAgent) { @@ -4899,12 +4908,23 @@ namespace OpenSim.Region.Framework.Scenes /// Get a group via its UUID /// /// - /// null if no group with that name exists + /// null if no group with that id exists public SceneObjectGroup GetSceneObjectGroup(UUID fullID) { return m_sceneGraph.GetSceneObjectGroup(fullID); } + /// + /// Get a group via its local ID + /// + /// This will only return a group if the local ID matches a root part + /// + /// null if no group with that id exists + public SceneObjectGroup GetSceneObjectGroup(uint localID) + { + return m_sceneGraph.GetSceneObjectGroup(localID); + } + /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) @@ -5065,14 +5085,15 @@ namespace OpenSim.Region.Framework.Scenes client.SendRegionHandle(regionID, handle); } - public bool NeedSceneCacheClear(UUID agentID) - { - IInventoryTransferModule inv = RequestModuleInterface(); - if (inv == null) - return true; - - return inv.NeedSceneCacheClear(agentID, this); - } +// Commented pending deletion since this method no longer appears to do anything at all +// public bool NeedSceneCacheClear(UUID agentID) +// { +// IInventoryTransferModule inv = RequestModuleInterface(); +// if (inv == null) +// return true; +// +// return inv.NeedSceneCacheClear(agentID, this); +// } public void CleanTempObjects() { diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 1beb5844ee..e599e908c7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1062,6 +1062,30 @@ namespace OpenSim.Region.Framework.Scenes return null; } + /// + /// Get a group in the scene + /// + /// + /// This will only return a group if the local ID matches the root part, not other parts. + /// + /// Local id of the root part of the group + /// null if no such group was found + protected internal SceneObjectGroup GetSceneObjectGroup(uint localID) + { + lock (SceneObjectGroupsByLocalPartID) + { + if (SceneObjectGroupsByLocalPartID.ContainsKey(localID)) + { + SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID]; + + if (so.LocalId == localID) + return so; + } + } + + return null; + } + /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index adb3d386bd..5be826db95 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.Framework.Scenes public ScriptControlled eventControls; } - public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); + public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); public class ScenePresence : EntityBase, IScenePresence { @@ -188,7 +188,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool SitGround { get; private set; } - private SendCourseLocationsMethod m_sendCourseLocationsMethod; + private SendCoarseLocationsMethod m_sendCoarseLocationsMethod; //private Vector3 m_requestedSitOffset = new Vector3(); @@ -711,7 +711,7 @@ namespace OpenSim.Region.Framework.Scenes AttachmentsSyncLock = new Object(); AllowMovement = true; IsChildAgent = true; - m_sendCourseLocationsMethod = SendCoarseLocationsDefault; + m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; Animator = new ScenePresenceAnimator(this); PresenceType = type; DrawDistance = world.DefaultDrawDistance; @@ -2629,17 +2629,17 @@ namespace OpenSim.Region.Framework.Scenes public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) { - SendCourseLocationsMethod d = m_sendCourseLocationsMethod; + SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod; if (d != null) { d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); } } - public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) + public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d) { if (d != null) - m_sendCourseLocationsMethod = d; + m_sendCoarseLocationsMethod = d; } public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) @@ -2843,7 +2843,7 @@ namespace OpenSim.Region.Framework.Scenes #region Significant Movement Method /// - /// This checks for a significant movement and sends a courselocationchange update + /// This checks for a significant movement and sends a coarselocationchange update /// protected void CheckForSignificantMovement() { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index d722a0990a..ac3da1e2cc 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -65,5 +65,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(scene.Frame, Is.EqualTo(1)); } + + [Test] + public void TestShutdownScene() + { + TestHelpers.InMethod(); + + Scene scene = new SceneHelpers().SetupScene(); + scene.Close(); + + Assert.That(scene.ShuttingDown, Is.True); + Assert.That(scene.Active, Is.False); + + // Trying to update a shutdown scene should result in no update + scene.Update(1); + + Assert.That(scene.Frame, Is.EqualTo(0)); + } } } \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index f3382b2081..c363fd33be 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -958,7 +958,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) + public void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible) { if (audible > 0 && message.Length > 0) IRC_SendChannelPrivmsg(fromName, message); diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs index 41ec14f224..7639c6ce45 100644 --- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs @@ -127,6 +127,9 @@ namespace OpenSim.Region.OptionalModules.Asset } string fileName = rawAssetId; + + if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName)) + return; using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) { diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index e22618dff3..5c3be29e9a 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -546,8 +546,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge c.SenderUUID = UUID.Zero; c.Scene = agent.Scene; - agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, - (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); + agent.ControllingClient.SendChatMessage( + msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero, + (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } private static void checkStringParameters(XmlRpcRequest request, string[] param) diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 66fc216913..5471afaf8f 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -607,13 +607,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public virtual void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { } - public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public virtual void SendChatMessage( + byte[] message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 07dd6137bf..a041ba8e0a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -105,7 +105,7 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; - shapeData.Size = Scale; + shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1> shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; @@ -144,7 +144,9 @@ public class BSCharacter : BSPhysObject ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; + BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); + BulletSimAPI.SetMargin2(BSShape.ptr, PhysicsScene.Params.collisionMargin); BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); if (PhysicsScene.Params.ccdMotionThreshold > 0f) @@ -156,11 +158,15 @@ public class BSCharacter : BSPhysObject OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + // Make so capsule does not fall over + BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); // Do this after the object has been added to the world @@ -175,11 +181,13 @@ public class BSCharacter : BSPhysObject } // No one calls this method so I don't know what it could possibly mean public override bool Stopped { get { return false; } } + public override OMV.Vector3 Size { get { // Avatar capsule size is kept in the scale parameter. - return _size; + // return _size; + return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); } set { @@ -199,7 +207,9 @@ public class BSCharacter : BSPhysObject } } + public override OMV.Vector3 Scale { get; set; } + public override PrimitiveBaseShape Shape { set { BaseShape = value; } @@ -264,7 +274,7 @@ public class BSCharacter : BSPhysObject // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain and being out of bounds. + // Check for being below terrain or on water. // Returns 'true' of the position was made sane by some action. private bool PositionSanityCheck() { @@ -335,7 +345,7 @@ public class BSCharacter : BSPhysObject } // Avatars don't do vehicles - public override int VehicleType { get { return 0; } set { return; } } + public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } public override void VehicleFloatParam(int param, float value) { } public override void VehicleVectorParam(int param, OMV.Vector3 value) {} public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } @@ -588,9 +598,8 @@ public class BSCharacter : BSPhysObject newScale.X = PhysicsScene.Params.avatarCapsuleRadius; newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, remote the capsule half spheres that are at each end - newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); - // newScale.Z = (size.Z * 2f); + // From the total height, remove the capsule half spheres that are at each end + newScale.Z = size.Z- (newScale.X + newScale.Y); Scale = newScale; } @@ -636,7 +645,7 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); } - // Tell the linkset about this + // Tell the linkset about value changes Linkset.UpdateProperties(this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index e686f2fdc7..db0c99e8d1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -692,7 +692,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process { - // swizzle a new list into the list location so we can process what's there int taintCount = m_taintsToProcessPerStep; TaintCallbackEntry oneCallback = new TaintCallbackEntry(); while (_taintedObjects.Count > 0 && taintCount-- > 0) @@ -711,7 +710,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { try { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG + DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); oneCallback.callback(); } catch (Exception e) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index b1833c5e88..30fa50a6fd 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -338,6 +338,7 @@ public class BSShapeCollection : IDisposable ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); + ret = true; haveShape = true; } // If the prim attributes are simple, this could be a simple Bullet native shape @@ -411,15 +412,14 @@ public class BSShapeCollection : IDisposable ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { + // release any previous shape + DereferenceShape(prim.BSShape, true, shapeCallback); shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; shapeData.Scale = shapeData.Size; - // release any previous shape - DereferenceShape(prim.BSShape, true, shapeCallback); - BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. @@ -443,7 +443,8 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, nativeShapeData.Scale), shapeType); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale) + , shapeType); DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); } else @@ -790,7 +791,6 @@ public class BSShapeCollection : IDisposable // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } - } if (mustRebuild || forceRebuild) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index ae267e3521..880859a12d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -333,8 +333,8 @@ public class BSTerrainManager // Make sure the new shape is processed. // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); - // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); + BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; }; diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 190fca0253..905540d36e 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -719,21 +719,21 @@ namespace OpenSim.Region.RegionCombinerModule rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); // Sets up the CoarseLocationUpdate forwarder for this root region - scene.EventManager.OnNewPresence += SetCourseLocationDelegate; + scene.EventManager.OnNewPresence += SetCoarseLocationDelegate; // Adds this root region to a dictionary of regions that are connectable m_regions.Add(scene.RegionInfo.originRegionID, rootConn); } } - private void SetCourseLocationDelegate(ScenePresence presence) + private void SetCoarseLocationDelegate(ScenePresence presence) { - presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); + presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates); } // This delegate was refactored for non-combined regions. // This combined region version will not use the pre-compiled lists of locations and ids - private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) + private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) { RegionConnections connectiondata = null; lock (m_regions) @@ -756,18 +756,18 @@ namespace OpenSim.Region.RegionCombinerModule } }); - DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); + DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); } - private void DistributeCourseLocationUpdates(List locations, List uuids, + private void DistributeCoarseLocationUpdates(List locations, List uuids, RegionConnections connectiondata, ScenePresence rootPresence) { RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); //List clients = new List(); - Dictionary updates = new Dictionary(); + Dictionary updates = new Dictionary(); // Root Region entry - RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); + RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct(); rootupdatedata.Locations = new List(); rootupdatedata.Uuids = new List(); rootupdatedata.Offset = Vector2.Zero; @@ -781,7 +781,7 @@ namespace OpenSim.Region.RegionCombinerModule foreach (RegionData regiondata in rdata) { Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); - RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); + RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; @@ -807,7 +807,7 @@ namespace OpenSim.Region.RegionCombinerModule if (!updates.ContainsKey(offset)) { // This shouldn't happen - RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); + RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs index 53a678f82f..224ac9947c 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs @@ -33,7 +33,7 @@ using OpenSim.Framework; namespace OpenSim.Region.RegionCombinerModule { - struct RegionCourseLocationStruct + struct RegionCoarseLocationStruct { public List Locations; public List Uuids; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index de49d6d8f7..8d8df1df0a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -11578,12 +11578,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void Deprecated(string command) { - throw new Exception("Command deprecated: " + command); + throw new ScriptException("Command deprecated: " + command); } internal void LSLError(string msg) { - throw new Exception("LSL Runtime Error: " + msg); + throw new ScriptException("LSL Runtime Error: " + msg); } public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 6809c09d05..8f348332b6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -95,13 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void MODError(string msg) { - throw new Exception("MOD Runtime Error: " + msg); + throw new ScriptException("MOD Runtime Error: " + msg); } - // - //Dumps an error message on the debug console. - // - + /// + /// Dumps an error message on the debug console. + /// + /// internal void MODShoutError(string message) { if (message.Length > 1023) @@ -359,20 +359,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result[i] = (string)(LSL_String)plist[i]; else if (plist[i] is LSL_Integer) result[i] = (int)(LSL_Integer)plist[i]; + // The int check exists because of the many plain old int script constants in ScriptBase which + // are not LSL_Integers. + else if (plist[i] is int) + result[i] = plist[i]; else if (plist[i] is LSL_Float) result[i] = (float)(LSL_Float)plist[i]; else if (plist[i] is LSL_Key) result[i] = new UUID((LSL_Key)plist[i]); else if (plist[i] is LSL_Rotation) - { - result[i] = (OpenMetaverse.Quaternion)( - (LSL_Rotation)plist[i]); - } + result[i] = (Quaternion)((LSL_Rotation)plist[i]); else if (plist[i] is LSL_Vector) - { - result[i] = (OpenMetaverse.Vector3)( - (LSL_Vector)plist[i]); - } + result[i] = (Vector3)((LSL_Vector)plist[i]); else MODError(String.Format("{0}: unknown LSL list element type", fname)); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 17277d7637..51c8c7ed89 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -218,7 +218,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - throw new Exception("OSSL Runtime Error: " + msg); + throw new ScriptException("OSSL Runtime Error: " + msg); } } @@ -1789,18 +1789,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected string LoadNotecard(string notecardNameOrUuid) { UUID assetID = CacheNotecard(notecardNameOrUuid); - StringBuilder notecardData = new StringBuilder(); - for (int count = 0; count < NotecardCache.GetLines(assetID); count++) + if (assetID != UUID.Zero) { - string line = NotecardCache.GetLine(assetID, count) + "\n"; - -// m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); - - notecardData.Append(line); + StringBuilder notecardData = new StringBuilder(); + + for (int count = 0; count < NotecardCache.GetLines(assetID); count++) + { + string line = NotecardCache.GetLine(assetID, count) + "\n"; + + // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); + + notecardData.Append(line); + } + + return notecardData.ToString(); } - return notecardData.ToString(); + return null; } /// @@ -2373,11 +2379,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } } + else + { + OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); + } } - if (appearance == null) - return new LSL_Key(UUID.Zero.ToString()); - UUID ownerID = UUID.Zero; if (owned) ownerID = m_host.OwnerID; @@ -2446,6 +2453,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; string appearanceSerialized = LoadNotecard(notecard); + + if (appearanceSerialized == null) + OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); + OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); @@ -3691,5 +3702,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api DropAttachmentAt(false, pos, rot); } + + public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) + { + CheckThreatLevel(ThreatLevel.Low, "osListenRegex"); + m_host.AddScriptLPS(1); + UUID keyID; + UUID.TryParse(ID, out keyID); + + // if we want the name to be used as a regular expression, ensure it is valid first. + if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME) + { + try + { + Regex.IsMatch("", name); + } + catch (Exception) + { + OSSLShoutError("Name regex is invalid."); + return -1; + } + } + + // if we want the msg to be used as a regular expression, ensure it is valid first. + if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) + { + try + { + Regex.IsMatch("", msg); + } + catch (Exception) + { + OSSLShoutError("Message regex is invalid."); + return -1; + } + } + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + return (wComm == null) ? -1 : wComm.Listen( + m_host.LocalId, + m_item.ItemID, + m_host.UUID, + channelID, + name, + keyID, + msg, + regexBitfield + ); + } + + public LSL_Integer osRegexIsMatch(string input, string pattern) + { + CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch"); + m_host.AddScriptLPS(1); + try + { + return Regex.IsMatch(input, pattern) ? 1 : 0; + } + catch (Exception) + { + OSSLShoutError("Possible invalid regular expression detected."); + return 0; + } + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index b1fbed5951..c447d1f6e3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -418,5 +418,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// void osForceDropAttachmentAt(vector pos, rotation rot); + + /// + /// Identical to llListen except for a bitfield which indicates which + /// string parameters should be parsed as regex patterns. + /// + /// + /// + /// + /// + /// + /// OS_LISTEN_REGEX_NAME + /// OS_LISTEN_REGEX_MESSAGE + /// + /// + LSL_Integer osListenRegex(int channelID, string name, string ID, + string msg, int regexBitfield); + + /// + /// Wraps to bool Regex.IsMatch(string input, string pattern) + /// + /// string to test for match + /// string to use as pattern + /// boolean + LSL_Integer osRegexIsMatch(string input, string pattern); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index bf66eb65e0..0dd5a57383 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -741,5 +741,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int KFM_CMD_PLAY = 0; public const int KFM_CMD_STOP = 1; public const int KFM_CMD_PAUSE = 2; + + /// + /// process name parameter as regex + /// + public const int OS_LISTEN_REGEX_NAME = 0x1; + + /// + /// process message parameter as regex + /// + public const int OS_LISTEN_REGEX_MESSAGE = 0x2; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index dee1b28cca..afa9ae0431 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -992,5 +992,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osForceDropAttachmentAt(pos, rot); } + + public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) + { + return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield); + } + + public LSL_Integer osRegexIsMatch(string input, string pattern) + { + return m_OSSL_Functions.osRegexIsMatch(input, pattern); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs new file mode 100644 index 0000000000..ae67fc5585 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs @@ -0,0 +1,40 @@ +/* + * 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; + +namespace OpenSim.Region.ScriptEngine.Shared +{ + public class ScriptException : Exception + { + public ScriptException() : base() {} + + public ScriptException(string message) : base(message) {} + + public ScriptException(string message, Exception innerException) : base(message, innerException) {} + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index c8718d9603..c40179456d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs @@ -75,76 +75,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_engine.AddRegion(m_scene); } - /// - /// Test creation of an NPC where the appearance data comes from a notecard - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromNotecard() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the appearance in the notecard. - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - /// - /// Test creation of an NPC where the appearance data comes from an avatar already in the region. - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromAvatar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the existing avatar's appearance - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - [Test] public void TestOsOwnerSaveAppearance() { diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index 25679a65c0..b49bcc2000 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -36,6 +36,7 @@ using OpenMetaverse; using OpenMetaverse.Assets; using OpenMetaverse.StructuredData; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.Attachments; using OpenSim.Region.CoreModules.Avatar.AvatarFactory; using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Region.Framework.Scenes; @@ -71,13 +72,193 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests config.Set("Enabled", "true"); m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); + SceneHelpers.SetupSceneModules( + m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); m_engine = new XEngine.XEngine(); m_engine.Initialise(initConfigSource); m_engine.AddRegion(m_scene); } + /// + /// Test creation of an NPC where the appearance data comes from a notecard + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromNotecard() + { + TestHelpers.InMethod(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float newHeight = 1.9f; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the appearance in the notecard. + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + + [Test] + public void TestOsNpcCreateNotExistingNotecard() + { + TestHelpers.InMethod(); + + UUID userId = TestHelpers.ParseTail(0x1); + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, so.RootPart, null); + + string npcRaw; + bool gotExpectedException = false; + try + { + npcRaw + = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); + } + catch (ScriptException) + { + gotExpectedException = true; + } + + Assert.That(gotExpectedException, Is.True); + } + + /// + /// Test creation of an NPC where the appearance data comes from an avatar already in the region. + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromAvatar() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float newHeight = 1.9f; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the existing avatar's appearance + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + + [Test] + public void TestOsNpcLoadAppearance() + { + TestHelpers.InMethod(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float firstHeight = 1.9f; + float secondHeight = 2.1f; + string firstAppearanceNcName = "appearanceNc1"; + string secondAppearanceNcName = "appearanceNc2"; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = firstHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + osslApi.osOwnerSaveAppearance(firstAppearanceNcName); + + string npcRaw + = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); + + // Create a second appearance notecard with a different height + sp.Appearance.AvatarHeight = secondHeight; + osslApi.osOwnerSaveAppearance(secondAppearanceNcName); + + osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight)); + } + + [Test] + public void TestOsNpcLoadAppearanceNotExistingNotecard() + { + TestHelpers.InMethod(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float firstHeight = 1.9f; + float secondHeight = 2.1f; + string firstAppearanceNcName = "appearanceNc1"; + string secondAppearanceNcName = "appearanceNc2"; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = firstHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + osslApi.osOwnerSaveAppearance(firstAppearanceNcName); + + string npcRaw + = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); + + bool gotExpectedException = false; + try + { + osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); + } + catch (ScriptException) + { + gotExpectedException = true; + } + + Assert.That(gotExpectedException, Is.True); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight)); + } + /// /// Test removal of an owned NPC. /// @@ -85,7 +266,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests public void TestOsNpcRemoveOwned() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); // Store an avatar with a different height from default in a notecard. UUID userId = TestHelpers.ParseTail(0x1); diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs index 46b0c672e2..4123f491bb 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs @@ -141,6 +141,9 @@ namespace OpenSim.Server.Handlers.Asset } string fileName = rawAssetId; + + if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName)) + return; using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) { diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 87ca944e67..ebdfb4f95e 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -531,13 +531,9 @@ namespace OpenSim.Tests.Common.Mock { } - public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) - { - } - - public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public virtual void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { } diff --git a/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml b/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml index 7498ae0af8..b570c554be 100644 --- a/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml +++ b/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml @@ -303,37 +303,37 @@
- +
- +
- +
- +
- +
- + diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index f976efe72b..fbc83e64c7 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index a00bc3ab01..65d3805bb3 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index acaa9c875f..936368a4d9 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 996ea21576..82fbad6966 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ