Merge branch 'master' into careminster
Conflicts: OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.csavinationmerge
commit
26cc57b6ca
|
@ -358,6 +358,9 @@ namespace OpenSim.Framework
|
|||
SetVisualParams(visualParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set avatar height by a calculation based on their visual parameters.
|
||||
/// </summary>
|
||||
public virtual void SetHeight()
|
||||
{
|
||||
// Start with shortest possible female avatar height
|
||||
|
|
|
@ -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,
|
||||
void SendChatMessage(
|
||||
string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source,
|
||||
byte audible);
|
||||
}
|
||||
}
|
|
@ -27,21 +27,134 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework.Console
|
||||
{
|
||||
public class ConsoleUtil
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public const int LocalIdNotFound = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Used by modules to display stock co-ordinate help, though possibly this should be under some general section
|
||||
/// rather than in each help summary.
|
||||
/// </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();
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given file path exists.
|
||||
/// </summary>
|
||||
/// <remarks>If not, warning is printed to the given console.</remarks>
|
||||
/// <returns>true if the file does not exist, false otherwise.</returns>
|
||||
/// <param name='console'></param>
|
||||
/// <param name='path'></param>
|
||||
public static bool CheckFileDoesNotExist(ICommandConsole console, string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
console.OutputFormat("File {0} already exists. Please move or remove it.", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to parse a console UUID from the console.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Will complain to the console if parsing fails.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
/// <param name='console'>If null then no complaint is printed.</param>
|
||||
/// <param name='rawUuid'></param>
|
||||
/// <param name='uuid'></param>
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (localId == 0)
|
||||
{
|
||||
if (console != null)
|
||||
console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse the input as either a UUID or a local ID.
|
||||
/// </summary>
|
||||
/// <returns>true if parsing succeeded, false otherwise.</returns>
|
||||
/// <param name='console'></param>
|
||||
/// <param name='rawId'></param>
|
||||
/// <param name='uuid'></param>
|
||||
/// <param name='localId'>
|
||||
/// Will be set to ConsoleUtil.LocalIdNotFound if parsing result was a UUID or no parse succeeded.
|
||||
/// </param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
||||
/// </summary>
|
||||
|
@ -112,3 +225,4 @@ public class ConsoleUtil
|
|||
return Vector3.TryParse(semiDigestedConsoleVector, out vector);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1112,7 +1112,19 @@ 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,
|
||||
/// <summary>
|
||||
/// Send chat to the viewer.
|
||||
/// </summary>
|
||||
/// <param name='message'></param>
|
||||
/// <param name='type'></param>
|
||||
/// <param name='fromPos'></param>
|
||||
/// <param name='fromName'></param>
|
||||
/// <param name='fromAgentID'></param>
|
||||
/// <param name='ownerID'></param>
|
||||
/// <param name='source'></param>
|
||||
/// <param name='audible'></param>
|
||||
void SendChatMessage(
|
||||
string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source,
|
||||
byte audible);
|
||||
|
||||
void SendInstantMessage(GridInstantMessage im);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,9 +268,17 @@ 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))
|
||||
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 name="fromPos"></param>
|
||||
/// <param name="regionPos">/param>
|
||||
/// <param name="fromAgentID"></param>
|
||||
/// <param name='ownerID'>
|
||||
/// 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
|
||||
/// </param>
|
||||
/// <param name="fromName"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="src"></param>
|
||||
/// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
|
||||
/// precondition</returns>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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<string, object> options)
|
||||
{
|
||||
if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath))
|
||||
return false;
|
||||
|
||||
if (m_scenes.Count > 0)
|
||||
{
|
||||
UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
|
||||
|
|
|
@ -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);
|
||||
|
||||
/// <summary>
|
||||
private List<Scene> m_Scenelist = new List<Scene>();
|
||||
private Dictionary<UUID, Scene> m_AgentRegions =
|
||||
new Dictionary<UUID, Scene>();
|
||||
// private Dictionary<UUID, Scene> m_AgentRegions =
|
||||
// new Dictionary<UUID, Scene>();
|
||||
|
||||
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<IInventoryTransferModule>(this);
|
||||
// scene.RegisterModuleInterface<IInventoryTransferModule>(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
|
||||
// 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
|
||||
// foreach (Scene s in m_Scenelist)
|
||||
// {
|
||||
// ScenePresence presence;
|
||||
//
|
||||
// If the agent is found in another scene
|
||||
// then the list wasn't current
|
||||
// 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;
|
||||
// }
|
||||
//
|
||||
// If the agent is totally unknown, then what
|
||||
// are we even doing here??
|
||||
// // 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;
|
||||
// }
|
||||
//
|
||||
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
|
||||
// // Another region has claimed the agent
|
||||
// //
|
||||
// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
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 void ClientLoggedOut(UUID agentID, Scene scene)
|
||||
// {
|
||||
// if (m_AgentRegions.ContainsKey(agentID))
|
||||
// m_AgentRegions.Remove(agentID);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|||
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||
/// <param name="channel">channel to listen on</param>
|
||||
/// <param name="name">name to filter on</param>
|
||||
/// <param name="id">key to filter on (user given, could be totally faked)</param>
|
||||
/// <param name="id">
|
||||
/// key to filter on (user given, could be totally faked)
|
||||
/// </param>
|
||||
/// <param name="msg">msg to filter on</param>
|
||||
/// <returns>number of the scripts handle</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="localID">localID of the script engine</param>
|
||||
/// <param name="itemID">UUID of the script engine</param>
|
||||
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||
/// <param name="channel">channel to listen on</param>
|
||||
/// <param name="name">name to filter on</param>
|
||||
/// <param name="id">
|
||||
/// key to filter on (user given, could be totally faked)
|
||||
/// </param>
|
||||
/// <param name="msg">msg to filter on</param>
|
||||
/// <param name="regexBitfield">
|
||||
/// Bitfield indicating which strings should be processed as regex.
|
||||
/// </param>
|
||||
/// <returns>number of the scripts handle</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -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<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg);
|
||||
List<ListenerInfo> 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<ListenerInfo> 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
|
||||
|
||||
/// <summary>
|
||||
/// process name parameter as regex
|
||||
/// </summary>
|
||||
public const int OS_LISTEN_REGEX_NAME = 0x1;
|
||||
|
||||
/// <summary>
|
||||
/// process message parameter as regex
|
||||
/// </summary>
|
||||
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,7 +780,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
|||
m_listeners[(int)item[2]].Add(info);
|
||||
}
|
||||
|
||||
idx+=6;
|
||||
idx+=dataItemLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -150,14 +152,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
|||
|
||||
List<string> 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<string, object> options)
|
||||
|
|
|
@ -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 <UUID>",
|
||||
"Delete a scene object by uuid",
|
||||
"Objects", false, "delete object id",
|
||||
"delete object id <UUID-or-localID>",
|
||||
"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 <start-coord> to <end-coord>",
|
||||
"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] <UUID>",
|
||||
"Show details of a scene object with the given UUID",
|
||||
"show object id",
|
||||
"show object id [--full] <UUID-or-localID>",
|
||||
"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 <UUID>",
|
||||
"Show details of a scene object parts with the given UUID", HandleShowPartByUuid);
|
||||
"show part id",
|
||||
"show part id <UUID-or-localID>",
|
||||
"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] <name>",
|
||||
"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 <start-coord> to <end-coord>",
|
||||
"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 <UUID-or-localID>",
|
||||
"Dump the formatted serialization of the given object to the file <UUID>.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] <uuid>");
|
||||
m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>");
|
||||
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 <UUID-or-localID>");
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append a scene object report to an input StringBuilder
|
||||
/// </summary>
|
||||
|
@ -641,18 +675,23 @@ 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<SceneObjectGroup>();
|
||||
|
||||
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);
|
||||
|
|
|
@ -45,6 +45,13 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
void Deactivate();
|
||||
void Activate();
|
||||
UUID GetID();
|
||||
|
||||
/// <summary>
|
||||
/// Bitfield indicating which strings should be processed as regex.
|
||||
/// 1 corresponds to IWorldCommListenerInfo::GetName()
|
||||
/// 2 corresponds to IWorldCommListenerInfo::GetMessage()
|
||||
/// </summary>
|
||||
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.
|
||||
/// </summary>
|
||||
/// <param name="localID">localID of the script engine</param>
|
||||
/// <param name="LocalID">localID of the script engine</param>
|
||||
/// <param name="itemID">UUID of the script engine</param>
|
||||
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||
/// <param name="channel">channel to listen on</param>
|
||||
|
@ -70,6 +77,23 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
/// <returns>number of the scripts handle</returns>
|
||||
int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg);
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="LocalID">localID of the script engine</param>
|
||||
/// <param name="itemID">UUID of the script engine</param>
|
||||
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||
/// <param name="channel">channel to listen on</param>
|
||||
/// <param name="name">name to filter on</param>
|
||||
/// <param name="id">key to filter on (user given, could be totally faked)</param>
|
||||
/// <param name="msg">msg to filter on</param>
|
||||
/// <param name="regexBitfield">Bitfield indicating which strings should be processed as regex.</param>
|
||||
/// <returns>number of the scripts handle</returns>
|
||||
int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield);
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -38,8 +38,20 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
public partial class Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// Send chat to listeners.
|
||||
/// </summary>
|
||||
/// <param name='message'></param>
|
||||
/// <param name='type'>/param>
|
||||
/// <param name='channel'></param>
|
||||
/// <param name='fromPos'></param>
|
||||
/// <param name='fromName'></param>
|
||||
/// <param name='fromID'></param>
|
||||
/// <param name='targetID'></param>
|
||||
/// <param name='fromAgent'></param>
|
||||
/// <param name='broadcast'></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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -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
|
||||
/// </summary>
|
||||
/// <param name="fullID"></param>
|
||||
/// <returns>null if no group with that name exists</returns>
|
||||
/// <returns>null if no group with that id exists</returns>
|
||||
public SceneObjectGroup GetSceneObjectGroup(UUID fullID)
|
||||
{
|
||||
return m_sceneGraph.GetSceneObjectGroup(fullID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a group via its local ID
|
||||
/// </summary>
|
||||
/// <remarks>This will only return a group if the local ID matches a root part</remarks>
|
||||
/// <param name="localID"></param>
|
||||
/// <returns>null if no group with that id exists</returns>
|
||||
public SceneObjectGroup GetSceneObjectGroup(uint localID)
|
||||
{
|
||||
return m_sceneGraph.GetSceneObjectGroup(localID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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<IInventoryTransferModule>();
|
||||
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<IInventoryTransferModule>();
|
||||
// if (inv == null)
|
||||
// return true;
|
||||
//
|
||||
// return inv.NeedSceneCacheClear(agentID, this);
|
||||
// }
|
||||
|
||||
public void CleanTempObjects()
|
||||
{
|
||||
|
|
|
@ -1062,6 +1062,30 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a group in the scene
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will only return a group if the local ID matches the root part, not other parts.
|
||||
/// </remarks>
|
||||
/// <param name="localID">Local id of the root part of the group</param>
|
||||
/// <returns>null if no such group was found</returns>
|
||||
protected internal SceneObjectGroup GetSceneObjectGroup(uint localID)
|
||||
{
|
||||
lock (SceneObjectGroupsByLocalPartID)
|
||||
{
|
||||
if (SceneObjectGroupsByLocalPartID.ContainsKey(localID))
|
||||
{
|
||||
SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID];
|
||||
|
||||
if (so.LocalId == localID)
|
||||
return so;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a group by name from the scene (will return the first
|
||||
/// found, if there are more than one prim with the same name)
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public ScriptControlled eventControls;
|
||||
}
|
||||
|
||||
public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs);
|
||||
public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs);
|
||||
|
||||
public class ScenePresence : EntityBase, IScenePresence
|
||||
{
|
||||
|
@ -188,7 +188,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
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<Vector3> coarseLocations, List<UUID> 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<Vector3> coarseLocations, List<UUID> avatarUUIDs)
|
||||
|
@ -2843,7 +2843,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
#region Significant Movement Method
|
||||
|
||||
/// <summary>
|
||||
/// This checks for a significant movement and sends a courselocationchange update
|
||||
/// This checks for a significant movement and sends a coarselocationchange update
|
||||
/// </summary>
|
||||
protected void CheckForSignificantMovement()
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -128,6 +128,9 @@ namespace OpenSim.Region.OptionalModules.Asset
|
|||
|
||||
string fileName = rawAssetId;
|
||||
|
||||
if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName))
|
||||
return;
|
||||
|
||||
using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(fs))
|
||||
|
|
|
@ -546,7 +546,8 @@ 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,
|
||||
agent.ControllingClient.SendChatMessage(
|
||||
msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero,
|
||||
(byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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<Vector3> coarseLocations, List<UUID> avatarUUIDs)
|
||||
private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> 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<Vector3> locations, List<UUID> uuids,
|
||||
private void DistributeCoarseLocationUpdates(List<Vector3> locations, List<UUID> uuids,
|
||||
RegionConnections connectiondata, ScenePresence rootPresence)
|
||||
{
|
||||
RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
|
||||
//List<IClientAPI> clients = new List<IClientAPI>();
|
||||
Dictionary<Vector2, RegionCourseLocationStruct> updates = new Dictionary<Vector2, RegionCourseLocationStruct>();
|
||||
Dictionary<Vector2, RegionCoarseLocationStruct> updates = new Dictionary<Vector2, RegionCoarseLocationStruct>();
|
||||
|
||||
// Root Region entry
|
||||
RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct();
|
||||
RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct();
|
||||
rootupdatedata.Locations = new List<Vector3>();
|
||||
rootupdatedata.Uuids = new List<UUID>();
|
||||
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<Vector3>();
|
||||
updatedata.Uuids = new List<UUID>();
|
||||
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<Vector3>();
|
||||
updatedata.Uuids = new List<UUID>();
|
||||
updatedata.Offset = offset;
|
||||
|
|
|
@ -33,7 +33,7 @@ using OpenSim.Framework;
|
|||
namespace OpenSim.Region.RegionCombinerModule
|
||||
{
|
||||
|
||||
struct RegionCourseLocationStruct
|
||||
struct RegionCoarseLocationStruct
|
||||
{
|
||||
public List<Vector3> Locations;
|
||||
public List<UUID> Uuids;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Dumps an error message on the debug console.
|
||||
/// </summary>
|
||||
/// <param name='message'></param>
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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,6 +1789,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
protected string LoadNotecard(string notecardNameOrUuid)
|
||||
{
|
||||
UUID assetID = CacheNotecard(notecardNameOrUuid);
|
||||
|
||||
if (assetID != UUID.Zero)
|
||||
{
|
||||
StringBuilder notecardData = new StringBuilder();
|
||||
|
||||
for (int count = 0; count < NotecardCache.GetLines(assetID); count++)
|
||||
|
@ -1803,6 +1806,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
return notecardData.ToString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache a notecard's contents.
|
||||
/// </summary>
|
||||
|
@ -2373,10 +2379,11 @@ 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)
|
||||
|
@ -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<IWorldComm>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -418,5 +418,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
|||
/// <param name="pos"></param>
|
||||
/// <param name="rot"></param>
|
||||
void osForceDropAttachmentAt(vector pos, rotation rot);
|
||||
|
||||
/// <summary>
|
||||
/// Identical to llListen except for a bitfield which indicates which
|
||||
/// string parameters should be parsed as regex patterns.
|
||||
/// </summary>
|
||||
/// <param name="channelID"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="ID"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="regexBitfield">
|
||||
/// OS_LISTEN_REGEX_NAME
|
||||
/// OS_LISTEN_REGEX_MESSAGE
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
LSL_Integer osListenRegex(int channelID, string name, string ID,
|
||||
string msg, int regexBitfield);
|
||||
|
||||
/// <summary>
|
||||
/// Wraps to bool Regex.IsMatch(string input, string pattern)
|
||||
/// </summary>
|
||||
/// <param name="input">string to test for match</param>
|
||||
/// <param name="regex">string to use as pattern</param>
|
||||
/// <returns>boolean</returns>
|
||||
LSL_Integer osRegexIsMatch(string input, string pattern);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// process name parameter as regex
|
||||
/// </summary>
|
||||
public const int OS_LISTEN_REGEX_NAME = 0x1;
|
||||
|
||||
/// <summary>
|
||||
/// process message parameter as regex
|
||||
/// </summary>
|
||||
public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
}
|
||||
}
|
|
@ -75,76 +75,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
|||
m_engine.AddRegion(m_scene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test creation of an NPC where the appearance data comes from a notecard
|
||||
/// </summary>
|
||||
[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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test creation of an NPC where the appearance data comes from an avatar already in the region.
|
||||
/// </summary>
|
||||
[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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test creation of an NPC where the appearance data comes from a notecard
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test creation of an NPC where the appearance data comes from an avatar already in the region.
|
||||
/// </summary>
|
||||
[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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test removal of an owned NPC.
|
||||
/// </summary>
|
||||
|
@ -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);
|
||||
|
|
|
@ -142,6 +142,9 @@ namespace OpenSim.Server.Handlers.Asset
|
|||
|
||||
string fileName = rawAssetId;
|
||||
|
||||
if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName))
|
||||
return;
|
||||
|
||||
using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(fs))
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -303,37 +303,37 @@
|
|||
<Key Name="fileName" Value="snd_TerrainStone.ogg" />
|
||||
</Section>
|
||||
<Section Name="snd_TerrainMetal">
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" />
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807201c9a66" />
|
||||
<Key Name="name" Value="snd_TerrainMetal" />
|
||||
<Key Name="assetType" Value="1" />
|
||||
<Key Name="fileName" Value="snd_TerrainMetal.ogg" />
|
||||
</Section>
|
||||
<Section Name="snd_TerrainGlass">
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" />
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807202c9a66" />
|
||||
<Key Name="name" Value="snd_TerrainGlass" />
|
||||
<Key Name="assetType" Value="1" />
|
||||
<Key Name="fileName" Value="snd_TerrainGlass.ogg" />
|
||||
</Section>
|
||||
<Section Name="snd_TerrainWood">
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" />
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807203c9a66" />
|
||||
<Key Name="name" Value="snd_TerrainWood" />
|
||||
<Key Name="assetType" Value="1" />
|
||||
<Key Name="fileName" Value="snd_TerrainWood.ogg" />
|
||||
</Section>
|
||||
<Section Name="snd_TerrainFlesh">
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" />
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807204c9a66" />
|
||||
<Key Name="name" Value="snd_TerrainFlesh" />
|
||||
<Key Name="assetType" Value="1" />
|
||||
<Key Name="fileName" Value="snd_TerrainFlesh.ogg" />
|
||||
</Section>
|
||||
<Section Name="snd_TerrainPlastic">
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" />
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807205c9a66" />
|
||||
<Key Name="name" Value="snd_TerrainPlastic" />
|
||||
<Key Name="assetType" Value="1" />
|
||||
<Key Name="fileName" Value="snd_TerrainPlastic.ogg" />
|
||||
</Section>
|
||||
<Section Name="snd_TerrainRubber">
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" />
|
||||
<Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807206c9a66" />
|
||||
<Key Name="name" Value="snd_TerrainRubber" />
|
||||
<Key Name="assetType" Value="1" />
|
||||
<Key Name="fileName" Value="snd_TerrainRubber.ogg" />
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue