Merge branch 'master' into careminster
Conflicts: OpenSim/Framework/Watchdog.cs OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs OpenSim/Region/Framework/Scenes/Scene.cs OpenSim/Region/Framework/Scenes/SceneObjectPart.cs OpenSim/Region/Framework/Scenes/ScenePresence.csavinationmerge
commit
0bc8238a6c
|
@ -1069,8 +1069,6 @@ namespace OpenSim.Data.Tests
|
||||||
regionInfo.RegionLocX = 0;
|
regionInfo.RegionLocX = 0;
|
||||||
regionInfo.RegionLocY = 0;
|
regionInfo.RegionLocY = 0;
|
||||||
|
|
||||||
Scene scene = new Scene(regionInfo);
|
|
||||||
|
|
||||||
SceneObjectPart sop = new SceneObjectPart();
|
SceneObjectPart sop = new SceneObjectPart();
|
||||||
sop.Name = name;
|
sop.Name = name;
|
||||||
sop.Description = name;
|
sop.Description = name;
|
||||||
|
@ -1081,7 +1079,7 @@ namespace OpenSim.Data.Tests
|
||||||
sop.Shape = PrimitiveBaseShape.Default;
|
sop.Shape = PrimitiveBaseShape.Default;
|
||||||
|
|
||||||
SceneObjectGroup sog = new SceneObjectGroup(sop);
|
SceneObjectGroup sog = new SceneObjectGroup(sop);
|
||||||
sog.SetScene(scene);
|
// sog.SetScene(scene);
|
||||||
|
|
||||||
return sog;
|
return sog;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,12 +101,24 @@ namespace OpenSim.Framework
|
||||||
private static Dictionary<int, ThreadWatchdogInfo> m_threads;
|
private static Dictionary<int, ThreadWatchdogInfo> m_threads;
|
||||||
private static System.Timers.Timer m_watchdogTimer;
|
private static System.Timers.Timer m_watchdogTimer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Last time the watchdog thread ran.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Should run every WATCHDOG_INTERVAL_MS
|
||||||
|
/// </remarks>
|
||||||
|
public static int LastWatchdogThreadTick { get; private set; }
|
||||||
|
|
||||||
static Watchdog()
|
static Watchdog()
|
||||||
{
|
{
|
||||||
m_threads = new Dictionary<int, ThreadWatchdogInfo>();
|
m_threads = new Dictionary<int, ThreadWatchdogInfo>();
|
||||||
m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
|
m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
|
||||||
m_watchdogTimer.AutoReset = false;
|
m_watchdogTimer.AutoReset = false;
|
||||||
m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
|
m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
|
||||||
|
|
||||||
|
// Set now so we don't get alerted on the first run
|
||||||
|
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
|
||||||
|
|
||||||
m_watchdogTimer.Start();
|
m_watchdogTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,6 +276,16 @@ namespace OpenSim.Framework
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
|
int now = Environment.TickCount & Int32.MaxValue;
|
||||||
|
int msElapsed = now - LastWatchdogThreadTick;
|
||||||
|
|
||||||
|
if (msElapsed > WATCHDOG_INTERVAL_MS * 2)
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms",
|
||||||
|
msElapsed, WATCHDOG_INTERVAL_MS);
|
||||||
|
|
||||||
|
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
|
||||||
|
|
||||||
Action<ThreadWatchdogInfo> callback = OnWatchdogTimeout;
|
Action<ThreadWatchdogInfo> callback = OnWatchdogTimeout;
|
||||||
|
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
|
@ -272,8 +294,6 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
lock (m_threads)
|
lock (m_threads)
|
||||||
{
|
{
|
||||||
int now = Environment.TickCount;
|
|
||||||
|
|
||||||
foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
|
foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
|
||||||
{
|
{
|
||||||
if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
|
if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
|
||||||
|
|
|
@ -92,9 +92,14 @@ namespace OpenSim
|
||||||
m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config");
|
m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.InfoFormat(
|
||||||
"[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture);
|
"[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture);
|
||||||
|
|
||||||
|
string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU");
|
||||||
|
|
||||||
|
m_log.InfoFormat(
|
||||||
|
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
|
||||||
|
|
||||||
// Increase the number of IOCP threads available. Mono defaults to a tragically low number
|
// Increase the number of IOCP threads available. Mono defaults to a tragically low number
|
||||||
int workerThreads, iocpThreads;
|
int workerThreads, iocpThreads;
|
||||||
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
|
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
|
||||||
|
@ -109,7 +114,6 @@ namespace OpenSim
|
||||||
|
|
||||||
// Check if the system is compatible with OpenSimulator.
|
// Check if the system is compatible with OpenSimulator.
|
||||||
// Ensures that the minimum system requirements are met
|
// Ensures that the minimum system requirements are met
|
||||||
m_log.Info("Performing compatibility checks... \n");
|
|
||||||
string supported = String.Empty;
|
string supported = String.Empty;
|
||||||
if (Util.IsEnvironmentSupported(ref supported))
|
if (Util.IsEnvironmentSupported(ref supported))
|
||||||
{
|
{
|
||||||
|
|
|
@ -257,16 +257,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
lock (sp.AttachmentsSyncLock)
|
lock (sp.AttachmentsSyncLock)
|
||||||
{
|
{
|
||||||
foreach (SceneObjectGroup grp in sp.GetAttachments())
|
foreach (SceneObjectGroup so in sp.GetAttachments())
|
||||||
{
|
{
|
||||||
grp.Scene.DeleteSceneObject(grp, false);
|
// We can only remove the script instances from the script engine after we've retrieved their xml state
|
||||||
|
// when we update the attachment item.
|
||||||
|
m_scene.DeleteSceneObject(so, false, false);
|
||||||
|
|
||||||
if (saveChanged || saveAllScripted)
|
if (saveChanged || saveAllScripted)
|
||||||
{
|
{
|
||||||
grp.IsAttachment = false;
|
so.IsAttachment = false;
|
||||||
grp.AbsolutePosition = grp.RootPart.AttachedPos;
|
so.AbsolutePosition = so.RootPart.AttachedPos;
|
||||||
UpdateKnownItem(sp, grp, saveAllScripted);
|
UpdateKnownItem(sp, so, saveAllScripted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
so.RemoveScriptInstances(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
sp.ClearAttachments();
|
sp.ClearAttachments();
|
||||||
|
@ -298,6 +302,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
|
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
|
||||||
// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
|
// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
|
||||||
|
|
||||||
|
if (group.GetSittingAvatarsCount() != 0)
|
||||||
|
{
|
||||||
|
// m_log.WarnFormat(
|
||||||
|
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
|
||||||
|
// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sp.GetAttachments(attachmentPt).Contains(group))
|
if (sp.GetAttachments(attachmentPt).Contains(group))
|
||||||
{
|
{
|
||||||
// m_log.WarnFormat(
|
// m_log.WarnFormat(
|
||||||
|
@ -357,8 +370,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
group.AttachmentPoint = attachmentPt;
|
group.AttachmentPoint = attachmentPt;
|
||||||
group.AbsolutePosition = attachPos;
|
group.AbsolutePosition = attachPos;
|
||||||
|
|
||||||
// We also don't want to do any of the inventory operations for an NPC.
|
|
||||||
if (sp.PresenceType != PresenceType.Npc)
|
if (sp.PresenceType != PresenceType.Npc)
|
||||||
|
UpdateUserInventoryWithAttachment(sp, group, attachmentPt);
|
||||||
|
|
||||||
|
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt)
|
||||||
{
|
{
|
||||||
// Remove any previous attachments
|
// Remove any previous attachments
|
||||||
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
||||||
|
@ -382,12 +403,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
|
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
|
public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
|
||||||
{
|
{
|
||||||
return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null);
|
return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null);
|
||||||
|
@ -721,79 +736,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
|
// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
|
||||||
// grp.Name, grp.LocalId, remoteClient.Name);
|
// grp.Name, grp.LocalId, remoteClient.Name);
|
||||||
|
|
||||||
// Vector3 inventoryStoredPosition = new Vector3
|
InventoryItemBase newItem
|
||||||
// (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
|
= m_invAccessModule.CopyToInventory(
|
||||||
// ? (float)Constants.RegionSize - 6
|
DeRezAction.TakeCopy,
|
||||||
// : grp.AbsolutePosition.X)
|
m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID,
|
||||||
// ,
|
new List<SceneObjectGroup> { grp },
|
||||||
// (grp.AbsolutePosition.Y > (int)Constants.RegionSize)
|
sp.ControllingClient, true)[0];
|
||||||
// ? (float)Constants.RegionSize - 6
|
|
||||||
// : grp.AbsolutePosition.Y,
|
|
||||||
// grp.AbsolutePosition.Z);
|
|
||||||
//
|
|
||||||
// Vector3 originalPosition = grp.AbsolutePosition;
|
|
||||||
//
|
|
||||||
// grp.AbsolutePosition = inventoryStoredPosition;
|
|
||||||
|
|
||||||
// If we're being called from a script, then trying to serialize that same script's state will not complete
|
|
||||||
// in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
|
|
||||||
// the client/server crashes rather than logging out normally, the attachment's scripts will resume
|
|
||||||
// without state on relog. Arguably, this is what we want anyway.
|
|
||||||
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false);
|
|
||||||
|
|
||||||
// grp.AbsolutePosition = originalPosition;
|
|
||||||
|
|
||||||
AssetBase asset = m_scene.CreateAsset(
|
|
||||||
grp.GetPartName(grp.LocalId),
|
|
||||||
grp.GetPartDescription(grp.LocalId),
|
|
||||||
(sbyte)AssetType.Object,
|
|
||||||
Utils.StringToBytes(sceneObjectXml),
|
|
||||||
sp.UUID);
|
|
||||||
|
|
||||||
m_scene.AssetService.Store(asset);
|
|
||||||
|
|
||||||
InventoryItemBase item = new InventoryItemBase();
|
|
||||||
item.CreatorId = grp.RootPart.CreatorID.ToString();
|
|
||||||
item.CreatorData = grp.RootPart.CreatorData;
|
|
||||||
item.Owner = sp.UUID;
|
|
||||||
item.ID = UUID.Random();
|
|
||||||
item.AssetID = asset.FullID;
|
|
||||||
item.Description = asset.Description;
|
|
||||||
item.Name = asset.Name;
|
|
||||||
item.AssetType = asset.Type;
|
|
||||||
item.InvType = (int)InventoryType.Object;
|
|
||||||
|
|
||||||
InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
|
|
||||||
if (folder != null)
|
|
||||||
item.Folder = folder.ID;
|
|
||||||
else // oopsies
|
|
||||||
item.Folder = UUID.Zero;
|
|
||||||
|
|
||||||
// Nix the special bits we used to use for slam and the folded perms
|
|
||||||
uint allowablePermissionsMask = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move);
|
|
||||||
|
|
||||||
if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions())
|
|
||||||
{
|
|
||||||
item.BasePermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
|
|
||||||
item.CurrentPermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
|
|
||||||
item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask;
|
|
||||||
item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
|
|
||||||
item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item.BasePermissions = grp.RootPart.BaseMask & allowablePermissionsMask;
|
|
||||||
item.CurrentPermissions = grp.RootPart.OwnerMask & allowablePermissionsMask;
|
|
||||||
item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask;
|
|
||||||
item.EveryOnePermissions = grp.RootPart.EveryoneMask & allowablePermissionsMask;
|
|
||||||
item.GroupPermissions = grp.RootPart.GroupMask & allowablePermissionsMask;
|
|
||||||
}
|
|
||||||
item.CreationDate = Util.UnixTimeSinceEpoch();
|
|
||||||
|
|
||||||
// sets itemID so client can show item as 'attached' in inventory
|
// sets itemID so client can show item as 'attached' in inventory
|
||||||
grp.FromItemID = item.ID;
|
grp.FromItemID = newItem.ID;
|
||||||
|
|
||||||
return item;
|
return newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so)
|
private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so)
|
||||||
|
@ -802,7 +755,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero);
|
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero);
|
||||||
sp.RemoveAttachment(so);
|
sp.RemoveAttachment(so);
|
||||||
m_scene.DeleteSceneObject(so, false);
|
|
||||||
|
// We can only remove the script instances from the script engine after we've retrieved their xml state
|
||||||
|
// when we update the attachment item.
|
||||||
|
m_scene.DeleteSceneObject(so, false, false);
|
||||||
|
|
||||||
// Prepare sog for storage
|
// Prepare sog for storage
|
||||||
so.AttachedAvatar = UUID.Zero;
|
so.AttachedAvatar = UUID.Zero;
|
||||||
|
@ -811,6 +767,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
so.AbsolutePosition = so.RootPart.AttachedPos;
|
so.AbsolutePosition = so.RootPart.AttachedPos;
|
||||||
|
|
||||||
UpdateKnownItem(sp, so, true);
|
UpdateKnownItem(sp, so, true);
|
||||||
|
so.RemoveScriptInstances(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
|
protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
|
||||||
|
@ -920,8 +877,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
item = m_scene.InventoryService.GetItem(item);
|
item = m_scene.InventoryService.GetItem(item);
|
||||||
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
|
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
|
||||||
if (changed && m_scene.AvatarFactory != null)
|
if (changed && m_scene.AvatarFactory != null)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
|
||||||
|
// sp.Name, att.Name, AttachmentPt);
|
||||||
|
|
||||||
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
Scene scene = CreateDefaultTestScene();
|
Scene scene = CreateDefaultTestScene();
|
||||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
|
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
|
||||||
|
|
||||||
string attName = "att";
|
string attName = "att";
|
||||||
|
|
||||||
|
@ -149,9 +149,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
|
InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
|
||||||
Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
|
Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
|
||||||
|
|
||||||
|
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||||
|
|
||||||
// TestHelpers.DisableLogging();
|
// TestHelpers.DisableLogging();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test that we do not attempt to attach an in-world object that someone else is sitting on.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestAddSatOnAttachmentFromGround()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
Scene scene = CreateDefaultTestScene();
|
||||||
|
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||||
|
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
|
||||||
|
|
||||||
|
string attName = "att";
|
||||||
|
|
||||||
|
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
|
||||||
|
|
||||||
|
UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(scene, 0x2);
|
||||||
|
ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, ua2);
|
||||||
|
|
||||||
|
// Put avatar within 10m of the prim so that sit doesn't fail.
|
||||||
|
sp2.AbsolutePosition = new Vector3(0, 0, 0);
|
||||||
|
sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
|
||||||
|
|
||||||
|
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false);
|
||||||
|
|
||||||
|
Assert.That(sp.HasAttachments(), Is.False);
|
||||||
|
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestAddAttachmentFromInventory()
|
public void TestAddAttachmentFromInventory()
|
||||||
{
|
{
|
||||||
|
@ -181,6 +213,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
// Check appearance status
|
// Check appearance status
|
||||||
Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
|
Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
|
||||||
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||||
|
|
||||||
|
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -239,6 +273,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
// Check item status
|
// Check item status
|
||||||
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
|
Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
|
||||||
|
|
||||||
|
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -300,6 +336,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID));
|
Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID));
|
||||||
Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
|
Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
|
||||||
Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
|
||||||
|
|
||||||
|
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -399,6 +437,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
|
Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
|
||||||
Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
|
Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
|
||||||
|
|
||||||
|
Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||||
|
|
||||||
// Check attachments have been removed from sceneA
|
// Check attachments have been removed from sceneA
|
||||||
ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
|
ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
|
||||||
|
|
||||||
|
@ -410,6 +450,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
// This is the actual attachment, which should no longer exist
|
// This is the actual attachment, which should no longer exist
|
||||||
List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
|
List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
|
||||||
Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
|
Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
|
||||||
|
|
||||||
|
Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// I'm commenting this test because scene setup NEEDS InventoryService to
|
// I'm commenting this test because scene setup NEEDS InventoryService to
|
||||||
|
|
|
@ -79,7 +79,6 @@
|
||||||
<RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" />
|
<RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" />
|
||||||
<RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \
|
<RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \
|
||||||
<RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \
|
<RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \
|
||||||
<RegionModule id="Warp3DImageModule" type="OpenSim.Region.CoreModules.World.Warp3DMap.Warp3DImageModule" /> \
|
|
||||||
|
|
||||||
</Extension>
|
</Extension>
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
void ResumeScripts();
|
void ResumeScripts();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop all the scripts in this entity.
|
/// Stop and remove all the scripts in this entity from the scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sceneObjectBeingDeleted">
|
/// <param name="sceneObjectBeingDeleted">
|
||||||
/// Should be true if these scripts are being removed because the scene
|
/// Should be true if these scripts are being removed because the scene
|
||||||
|
@ -100,6 +100,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// </param>
|
/// </param>
|
||||||
void RemoveScriptInstances(bool sceneObjectBeingDeleted);
|
void RemoveScriptInstances(bool sceneObjectBeingDeleted);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop all the scripts in this entity.
|
||||||
|
/// </summary>
|
||||||
|
void StopScriptInstances();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start a script which is in this entity's inventory.
|
/// Start a script which is in this entity's inventory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -131,7 +136,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
|
ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop a script which is in this prim's inventory.
|
/// Stop and remove a script which is in this prim's inventory from the scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemId"></param>
|
/// <param name="itemId"></param>
|
||||||
/// <param name="sceneObjectBeingDeleted">
|
/// <param name="sceneObjectBeingDeleted">
|
||||||
|
@ -140,6 +145,12 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// </param>
|
/// </param>
|
||||||
void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted);
|
void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop a script which is in this prim's inventory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemId"></param>
|
||||||
|
void StopScriptInstance(UUID itemId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
|
/// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
|
||||||
/// name is chosen.
|
/// name is chosen.
|
||||||
|
|
|
@ -183,6 +183,14 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// <returns>true if the stand succeeded, false if not</returns>
|
/// <returns>true if the stand succeeded, false if not</returns>
|
||||||
bool Stand(UUID agentID, Scene scene);
|
bool Stand(UUID agentID, Scene scene);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the NPC to touch an object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agentID"></param>
|
||||||
|
/// <param name="partID"></param>
|
||||||
|
/// <returns>true if the touch is actually attempted, false if not</returns>
|
||||||
|
bool Touch(UUID agentID, UUID partID);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete an NPC.
|
/// Delete an NPC.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -2281,13 +2281,30 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Synchronously delete the given object from the scene.
|
/// Synchronously delete the given object from the scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Scripts are also removed.
|
||||||
|
/// </remarks>
|
||||||
/// <param name="group">Object Id</param>
|
/// <param name="group">Object Id</param>
|
||||||
/// <param name="silent">Suppress broadcasting changes to other clients.</param>
|
/// <param name="silent">Suppress broadcasting changes to other clients.</param>
|
||||||
public void DeleteSceneObject(SceneObjectGroup group, bool silent)
|
public void DeleteSceneObject(SceneObjectGroup group, bool silent)
|
||||||
{
|
{
|
||||||
|
DeleteSceneObject(group, silent, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Synchronously delete the given object from the scene.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="group">Object Id</param>
|
||||||
|
/// <param name="silent">Suppress broadcasting changes to other clients.</param>
|
||||||
|
/// <param name="removeScripts">If true, then scripts are removed. If false, then they are only stopped.</para>
|
||||||
|
public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts)
|
||||||
|
{
|
||||||
// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
|
// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
|
||||||
|
|
||||||
|
if (removeScripts)
|
||||||
group.RemoveScriptInstances(true);
|
group.RemoveScriptInstances(true);
|
||||||
|
else
|
||||||
|
group.StopScriptInstances();
|
||||||
|
|
||||||
SceneObjectPart[] partList = group.Parts;
|
SceneObjectPart[] partList = group.Parts;
|
||||||
|
|
||||||
|
@ -2595,7 +2612,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[SCENE]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace);
|
m_log.WarnFormat("[INTERREGION]: Problem casting object, exception {0}{1}", e.Message, e.StackTrace);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user is banned, we won't let any of their objects
|
||||||
|
// enter. Period.
|
||||||
|
//
|
||||||
|
if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID, 36))
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2606,14 +2632,28 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (!AddSceneObject(newObject))
|
if (!AddSceneObject(newObject))
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[SCENE]: Problem adding scene object {0} in {1} ", sog.UUID, RegionInfo.RegionName);
|
m_log.DebugFormat(
|
||||||
|
"[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newObject.IsAttachment)
|
||||||
|
{
|
||||||
|
// FIXME: It would be better to never add the scene object at all rather than add it and then delete
|
||||||
|
// it
|
||||||
|
if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition))
|
||||||
|
{
|
||||||
|
// Deny non attachments based on parcel settings
|
||||||
|
//
|
||||||
|
m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
|
||||||
|
|
||||||
|
DeleteSceneObject(newObject, false);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For attachments, we need to wait until the agent is root
|
// For attachments, we need to wait until the agent is root
|
||||||
// before we restart the scripts, or else some functions won't work.
|
// before we restart the scripts, or else some functions won't work.
|
||||||
if (!newObject.IsAttachment)
|
|
||||||
{
|
|
||||||
newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
|
newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
|
||||||
newObject.ResumeScripts();
|
newObject.ResumeScripts();
|
||||||
}
|
}
|
||||||
|
@ -2650,8 +2690,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sceneObject.SetScene(this);
|
|
||||||
|
|
||||||
// Force allocation of new LocalId
|
// Force allocation of new LocalId
|
||||||
//
|
//
|
||||||
SceneObjectPart[] parts = sceneObject.Parts;
|
SceneObjectPart[] parts = sceneObject.Parts;
|
||||||
|
@ -2707,18 +2745,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AddRestoredSceneObject(sceneObject, true, false);
|
AddRestoredSceneObject(sceneObject, true, false);
|
||||||
|
|
||||||
if (!Permissions.CanObjectEntry(sceneObject.UUID,
|
|
||||||
true, sceneObject.AbsolutePosition))
|
|
||||||
{
|
|
||||||
// Deny non attachments based on parcel settings
|
|
||||||
//
|
|
||||||
m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
|
|
||||||
|
|
||||||
DeleteSceneObject(sceneObject, false);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -4653,6 +4679,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_sceneGraph.ForEachScenePresence(action);
|
m_sceneGraph.ForEachScenePresence(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all the scene object groups.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The scene object groups. If the scene is empty then an empty list is returned.
|
||||||
|
/// </returns>
|
||||||
|
public List<SceneObjectGroup> GetSceneObjectGroups()
|
||||||
|
{
|
||||||
|
return m_sceneGraph.GetSceneObjectGroups();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a group via its UUID
|
/// Get a group via its UUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -401,9 +401,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (Entities.ContainsKey(sceneObject.UUID))
|
if (Entities.ContainsKey(sceneObject.UUID))
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
// "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()",
|
"[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()",
|
||||||
// m_parentScene.RegionInfo.RegionName, sceneObject.UUID);
|
m_parentScene.RegionInfo.RegionName, sceneObject.UUID);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1037,6 +1037,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all the scene object groups.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The scene object groups. If the scene is empty then an empty list is returned.
|
||||||
|
/// </returns>
|
||||||
|
protected internal List<SceneObjectGroup> GetSceneObjectGroups()
|
||||||
|
{
|
||||||
|
lock (SceneObjectGroupsByFullID)
|
||||||
|
return new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a group in the scene
|
/// Get a group in the scene
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1180,11 +1192,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="action"></param>
|
/// <param name="action"></param>
|
||||||
protected internal void ForEachSOG(Action<SceneObjectGroup> action)
|
protected internal void ForEachSOG(Action<SceneObjectGroup> action)
|
||||||
{
|
{
|
||||||
List<SceneObjectGroup> objlist;
|
foreach (SceneObjectGroup obj in GetSceneObjectGroups())
|
||||||
lock (SceneObjectGroupsByFullID)
|
|
||||||
objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
|
|
||||||
|
|
||||||
foreach (SceneObjectGroup obj in objlist)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop the scripts contained in all the prims in this group
|
/// Stop and remove the scripts contained in all the prims in this group
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
|
public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
|
||||||
{
|
{
|
||||||
|
@ -88,6 +88,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
|
parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop the scripts contained in all the prims in this group
|
||||||
|
/// </summary>
|
||||||
|
public void StopScriptInstances()
|
||||||
|
{
|
||||||
|
Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => p.Inventory.StopScriptInstances());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add an inventory item from a user's inventory to a prim in this scene object.
|
/// Add an inventory item from a user's inventory to a prim in this scene object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1675,16 +1675,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
|
return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Added as a way for the storage provider to reset the scene,
|
|
||||||
/// most likely a better way to do this sort of thing but for now...
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="scene"></param>
|
|
||||||
public void SetScene(Scene scene)
|
|
||||||
{
|
|
||||||
m_scene = scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set a part to act as the root part for this scene object
|
/// Set a part to act as the root part for this scene object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -4324,6 +4314,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of sitting avatars.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int GetSittingAvatarsCount()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => count += p.GetSittingAvatarsCount());
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
|
return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
|
||||||
|
|
|
@ -147,6 +147,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
get { return ParentGroup.RootPart == this; }
|
get { return ParentGroup.RootPart == this; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is an explicit sit target set for this part?
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSitTargetSet
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return
|
||||||
|
!(SitTargetPosition == Vector3.Zero
|
||||||
|
&& (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion
|
||||||
|
|| SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 1f && SitTargetOrientation.W == 0f // W-Z Mapping was invalid at one point
|
||||||
|
|| SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f && SitTargetOrientation.W == 0f)); // Invalid Quaternion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
public bool AllowedDrop;
|
public bool AllowedDrop;
|
||||||
|
@ -426,7 +441,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
private uint _category;
|
private uint _category;
|
||||||
private Int32 _creationDate;
|
private Int32 _creationDate;
|
||||||
private uint _parentID = 0;
|
private uint _parentID = 0;
|
||||||
private UUID m_sitTargetAvatar = UUID.Zero;
|
|
||||||
private uint _baseMask = (uint)PermissionMask.All;
|
private uint _baseMask = (uint)PermissionMask.All;
|
||||||
private uint _ownerMask = (uint)PermissionMask.All;
|
private uint _ownerMask = (uint)PermissionMask.All;
|
||||||
private uint _groupMask = (uint)PermissionMask.None;
|
private uint _groupMask = (uint)PermissionMask.None;
|
||||||
|
@ -1312,13 +1326,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
|
/// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UUID SitTargetAvatar
|
public UUID SitTargetAvatar { get; set; }
|
||||||
{
|
|
||||||
get { return m_sitTargetAvatar; }
|
/// <summary>
|
||||||
set { m_sitTargetAvatar = value; }
|
/// IDs of all avatars start on this object part.
|
||||||
}
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// We need to track this so that we can stop sat upon prims from being attached.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>
|
||||||
|
/// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene.
|
||||||
|
/// </value>
|
||||||
|
private HashSet<UUID> m_sittingAvatars;
|
||||||
|
|
||||||
public virtual UUID RegionID
|
public virtual UUID RegionID
|
||||||
{
|
{
|
||||||
|
@ -5128,5 +5149,99 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Inventory.UpdateInventoryItem(item, false, false);
|
Inventory.UpdateInventoryItem(item, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Record an avatar sitting on this part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This is called for all the sitting avatars whether there is a sit target set or not.</remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// true if the avatar was not already recorded, false otherwise.
|
||||||
|
/// </returns>
|
||||||
|
/// <param name='avatarId'></param>
|
||||||
|
protected internal bool AddSittingAvatar(UUID avatarId)
|
||||||
|
{
|
||||||
|
if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
|
||||||
|
SitTargetAvatar = avatarId;
|
||||||
|
|
||||||
|
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||||
|
|
||||||
|
if (sittingAvatars == null)
|
||||||
|
sittingAvatars = new HashSet<UUID>();
|
||||||
|
|
||||||
|
lock (sittingAvatars)
|
||||||
|
{
|
||||||
|
m_sittingAvatars = sittingAvatars;
|
||||||
|
return m_sittingAvatars.Add(avatarId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove an avatar recorded as sitting on this part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// true if the avatar was present and removed, false if it was not present.
|
||||||
|
/// </returns>
|
||||||
|
/// <param name='avatarId'></param>
|
||||||
|
protected internal bool RemoveSittingAvatar(UUID avatarId)
|
||||||
|
{
|
||||||
|
if (SitTargetAvatar == avatarId)
|
||||||
|
SitTargetAvatar = UUID.Zero;
|
||||||
|
|
||||||
|
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||||
|
|
||||||
|
// This can occur under a race condition where another thread
|
||||||
|
if (sittingAvatars == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lock (sittingAvatars)
|
||||||
|
{
|
||||||
|
if (sittingAvatars.Remove(avatarId))
|
||||||
|
{
|
||||||
|
if (sittingAvatars.Count == 0)
|
||||||
|
m_sittingAvatars = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a copy of the list of sitting avatars.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
|
||||||
|
/// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
|
||||||
|
public HashSet<UUID> GetSittingAvatars()
|
||||||
|
{
|
||||||
|
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||||
|
|
||||||
|
if (sittingAvatars == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (sittingAvatars)
|
||||||
|
return new HashSet<UUID>(sittingAvatars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of sitting avatars.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int GetSittingAvatarsCount()
|
||||||
|
{
|
||||||
|
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||||
|
|
||||||
|
if (sittingAvatars == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lock (sittingAvatars)
|
||||||
|
return sittingAvatars.Count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,7 +292,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop all the scripts in this prim.
|
/// Stop and remove all the scripts in this prim.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sceneObjectBeingDeleted">
|
/// <param name="sceneObjectBeingDeleted">
|
||||||
/// Should be true if these scripts are being removed because the scene
|
/// Should be true if these scripts are being removed because the scene
|
||||||
|
@ -308,6 +308,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop all the scripts in this prim.
|
||||||
|
/// </summary>
|
||||||
|
public void StopScriptInstances()
|
||||||
|
{
|
||||||
|
GetInventoryItems(InventoryType.LSL).ForEach(i => StopScriptInstance(i));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start a script which is in this prim's inventory.
|
/// Start a script which is in this prim's inventory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -596,7 +604,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop a script which is in this prim's inventory.
|
/// Stop and remove a script which is in this prim's inventory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemId"></param>
|
/// <param name="itemId"></param>
|
||||||
/// <param name="sceneObjectBeingDeleted">
|
/// <param name="sceneObjectBeingDeleted">
|
||||||
|
@ -615,7 +623,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
m_log.WarnFormat(
|
||||||
"[PRIM INVENTORY]: " +
|
"[PRIM INVENTORY]: " +
|
||||||
"Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
|
"Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
|
||||||
itemId, m_part.Name, m_part.UUID,
|
itemId, m_part.Name, m_part.UUID,
|
||||||
|
@ -623,6 +631,51 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop a script which is in this prim's inventory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemId"></param>
|
||||||
|
/// <param name="sceneObjectBeingDeleted">
|
||||||
|
/// Should be true if this script is being removed because the scene
|
||||||
|
/// object is being deleted. This will prevent spurious updates to the client.
|
||||||
|
/// </param>
|
||||||
|
public void StopScriptInstance(UUID itemId)
|
||||||
|
{
|
||||||
|
TaskInventoryItem scriptItem;
|
||||||
|
|
||||||
|
lock (m_items)
|
||||||
|
m_items.TryGetValue(itemId, out scriptItem);
|
||||||
|
|
||||||
|
if (scriptItem != null)
|
||||||
|
{
|
||||||
|
StopScriptInstance(scriptItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[PRIM INVENTORY]: " +
|
||||||
|
"Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
|
||||||
|
itemId, m_part.Name, m_part.UUID,
|
||||||
|
m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop a script which is in this prim's inventory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemId"></param>
|
||||||
|
/// <param name="sceneObjectBeingDeleted">
|
||||||
|
/// Should be true if this script is being removed because the scene
|
||||||
|
/// object is being deleted. This will prevent spurious updates to the client.
|
||||||
|
/// </param>
|
||||||
|
public void StopScriptInstance(TaskInventoryItem item)
|
||||||
|
{
|
||||||
|
m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
|
||||||
|
|
||||||
|
// At the moment, even stopped scripts are counted as active, which is probably wrong.
|
||||||
|
// m_part.ParentGroup.AddActiveScriptCount(-1);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if the inventory holds an item with a given name.
|
/// Check if the inventory holds an item with a given name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -593,6 +593,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
private UUID m_parentUUID = UUID.Zero;
|
private UUID m_parentUUID = UUID.Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Are we sitting on an object?
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>A more readable way of testing presence sit status than ParentID == 0</remarks>
|
||||||
|
public bool IsSatOnObject { get { return ParentID != 0; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
|
/// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1940,10 +1946,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset sit target.
|
|
||||||
if (part.SitTargetAvatar == UUID)
|
|
||||||
part.SitTargetAvatar = UUID.Zero;
|
|
||||||
|
|
||||||
part.ParentGroup.DeleteAvatar(UUID);
|
part.ParentGroup.DeleteAvatar(UUID);
|
||||||
// ParentPosition = part.GetWorldPosition();
|
// ParentPosition = part.GetWorldPosition();
|
||||||
ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
|
ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
|
||||||
|
@ -1961,6 +1963,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
SendAvatarDataToAllAgents();
|
SendAvatarDataToAllAgents();
|
||||||
m_requestedSitTargetID = 0;
|
m_requestedSitTargetID = 0;
|
||||||
|
|
||||||
|
part.RemoveSittingAvatar(UUID);
|
||||||
|
|
||||||
if (part != null)
|
if (part != null)
|
||||||
part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
|
part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
}
|
}
|
||||||
|
@ -1994,15 +1998,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//look for prims with explicit sit targets that are available
|
//look for prims with explicit sit targets that are available
|
||||||
foreach (SceneObjectPart part in partArray)
|
foreach (SceneObjectPart part in partArray)
|
||||||
{
|
{
|
||||||
// Is a sit target available?
|
if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
|
||||||
Vector3 avSitOffset = part.SitTargetPosition;
|
|
||||||
Quaternion avSitOrientation = part.SitTargetOrientation;
|
|
||||||
UUID avOnTargetAlready = part.SitTargetAvatar;
|
|
||||||
|
|
||||||
bool SitTargetUnOccupied = avOnTargetAlready == UUID.Zero;
|
|
||||||
bool SitTargetisSet = avSitOffset != Vector3.Zero || avSitOrientation != Quaternion.Identity;
|
|
||||||
|
|
||||||
if (SitTargetisSet && SitTargetUnOccupied)
|
|
||||||
{
|
{
|
||||||
//switch the target to this prim
|
//switch the target to this prim
|
||||||
return part;
|
return part;
|
||||||
|
@ -2013,10 +2009,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return targetPart;
|
return targetPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendSitResponse(UUID targetID, Vector3 offset, Quaternion pSitOrientation)
|
private void SendSitResponse(UUID targetID, Vector3 offset, Quaternion sitOrientation)
|
||||||
{
|
{
|
||||||
Vector3 pos = new Vector3();
|
|
||||||
Quaternion sitOrientation = pSitOrientation;
|
|
||||||
Vector3 cameraEyeOffset = Vector3.Zero;
|
Vector3 cameraEyeOffset = Vector3.Zero;
|
||||||
Vector3 cameraAtOffset = Vector3.Zero;
|
Vector3 cameraAtOffset = Vector3.Zero;
|
||||||
bool forceMouselook = false;
|
bool forceMouselook = false;
|
||||||
|
@ -2028,43 +2022,22 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// TODO: determine position to sit at based on scene geometry; don't trust offset from client
|
// TODO: determine position to sit at based on scene geometry; don't trust offset from client
|
||||||
// see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
|
// see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
|
||||||
|
|
||||||
// Is a sit target available?
|
|
||||||
Vector3 avSitOffSet = part.SitTargetPosition;
|
|
||||||
Quaternion avSitOrientation = part.SitTargetOrientation;
|
|
||||||
UUID avOnTargetAlready = part.SitTargetAvatar;
|
|
||||||
|
|
||||||
bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
|
|
||||||
bool SitTargetisSet =
|
|
||||||
(!(avSitOffSet == Vector3.Zero &&
|
|
||||||
(
|
|
||||||
avSitOrientation == Quaternion.Identity // Valid Zero Rotation quaternion
|
|
||||||
|| avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point
|
|
||||||
|| avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
// m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied);
|
|
||||||
|
|
||||||
if (PhysicsActor != null)
|
if (PhysicsActor != null)
|
||||||
m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
|
m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
|
||||||
|
|
||||||
bool canSit = false;
|
bool canSit = false;
|
||||||
pos = part.AbsolutePosition + offset;
|
Vector3 pos = part.AbsolutePosition + offset;
|
||||||
|
|
||||||
if (SitTargetisSet)
|
if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
|
||||||
{
|
|
||||||
if (SitTargetUnOccupied)
|
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
|
// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
|
||||||
// Name, part.Name, part.LocalId);
|
// Name, part.Name, part.LocalId);
|
||||||
|
|
||||||
part.SitTargetAvatar = UUID;
|
offset = part.SitTargetPosition;
|
||||||
offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
|
sitOrientation = part.SitTargetOrientation;
|
||||||
sitOrientation = avSitOrientation;
|
|
||||||
canSit = true;
|
canSit = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
|
if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
|
||||||
|
@ -2076,6 +2049,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
|
AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
|
||||||
canSit = true;
|
canSit = true;
|
||||||
}
|
}
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m",
|
||||||
|
// Name, part.Name, part.LocalId);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canSit)
|
if (canSit)
|
||||||
|
@ -2086,6 +2065,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
RemoveFromPhysicalScene();
|
RemoveFromPhysicalScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
part.AddSittingAvatar(UUID);
|
||||||
|
|
||||||
cameraAtOffset = part.GetCameraAtOffset();
|
cameraAtOffset = part.GetCameraAtOffset();
|
||||||
cameraEyeOffset = part.GetCameraEyeOffset();
|
cameraEyeOffset = part.GetCameraEyeOffset();
|
||||||
forceMouselook = part.GetForceMouselook();
|
forceMouselook = part.GetForceMouselook();
|
||||||
|
@ -2362,6 +2343,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (part != null)
|
if (part != null)
|
||||||
{
|
{
|
||||||
|
if (part.ParentGroup.IsAttachment)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[SCENE PRESENCE]: Avatar {0} tried to sit on part {1} from object {2} in {3} but this is an attachment for avatar id {4}",
|
||||||
|
Name, part.Name, part.ParentGroup.Name, Scene.Name, part.ParentGroup.AttachedAvatar);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (part.SitTargetAvatar == UUID)
|
if (part.SitTargetAvatar == UUID)
|
||||||
{
|
{
|
||||||
Vector3 sitTargetPos = part.SitTargetPosition;
|
Vector3 sitTargetPos = part.SitTargetPosition;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
@ -69,6 +70,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
|
m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
|
||||||
|
|
||||||
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
||||||
|
Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0));
|
||||||
|
Assert.That(part.GetSittingAvatars(), Is.Null);
|
||||||
Assert.That(m_sp.ParentID, Is.EqualTo(0));
|
Assert.That(m_sp.ParentID, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +89,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
|
||||||
m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
|
m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
|
||||||
|
|
||||||
|
Assert.That(m_sp.PhysicsActor, Is.Null);
|
||||||
|
|
||||||
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
||||||
|
Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
|
||||||
|
HashSet<UUID> sittingAvatars = part.GetSittingAvatars();
|
||||||
|
Assert.That(sittingAvatars.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(sittingAvatars.Contains(m_sp.UUID));
|
||||||
Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
|
Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,10 +113,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
|
|
||||||
m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
|
m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
|
||||||
|
|
||||||
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
|
||||||
Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
|
|
||||||
Assert.That(m_sp.PhysicsActor, Is.Null);
|
|
||||||
|
|
||||||
// FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
|
// FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
|
||||||
// default avatar.
|
// default avatar.
|
||||||
// Curiously, Vector3.ToString() will not display the last two places of the float. For example,
|
// Curiously, Vector3.ToString() will not display the last two places of the float. For example,
|
||||||
|
@ -119,6 +124,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
m_sp.StandUp();
|
m_sp.StandUp();
|
||||||
|
|
||||||
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
||||||
|
Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0));
|
||||||
|
Assert.That(part.GetSittingAvatars(), Is.Null);
|
||||||
Assert.That(m_sp.ParentID, Is.EqualTo(0));
|
Assert.That(m_sp.ParentID, Is.EqualTo(0));
|
||||||
Assert.That(m_sp.PhysicsActor, Is.Not.Null);
|
Assert.That(m_sp.PhysicsActor, Is.Not.Null);
|
||||||
}
|
}
|
||||||
|
@ -145,11 +152,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
|
Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
|
||||||
Assert.That(m_sp.PhysicsActor, Is.Null);
|
Assert.That(m_sp.PhysicsActor, Is.Null);
|
||||||
|
|
||||||
|
Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
|
||||||
|
HashSet<UUID> sittingAvatars = part.GetSittingAvatars();
|
||||||
|
Assert.That(sittingAvatars.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(sittingAvatars.Contains(m_sp.UUID));
|
||||||
|
|
||||||
m_sp.StandUp();
|
m_sp.StandUp();
|
||||||
|
|
||||||
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
||||||
Assert.That(m_sp.ParentID, Is.EqualTo(0));
|
Assert.That(m_sp.ParentID, Is.EqualTo(0));
|
||||||
Assert.That(m_sp.PhysicsActor, Is.Not.Null);
|
Assert.That(m_sp.PhysicsActor, Is.Not.Null);
|
||||||
|
|
||||||
|
Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
|
||||||
|
Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0));
|
||||||
|
Assert.That(part.GetSittingAvatars(), Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -228,7 +228,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
|
||||||
// m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
|
// m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
|
||||||
// m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
|
// m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
|
||||||
|
|
||||||
m_log.InfoFormat("[RegionReady]: Initialization complete - logins enabled for {0}", m_scene.RegionInfo.RegionName);
|
m_log.InfoFormat(
|
||||||
|
"[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
|
||||||
|
|
||||||
if (m_uri != string.Empty)
|
if (m_uri != string.Empty)
|
||||||
{
|
{
|
||||||
|
|
|
@ -104,6 +104,45 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment");
|
OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Touch(UUID target)
|
||||||
|
{
|
||||||
|
SceneObjectPart part = m_scene.GetSceneObjectPart(target);
|
||||||
|
if (part == null)
|
||||||
|
return false;
|
||||||
|
bool objectTouchable = hasTouchEvents(part); // Only touch an object that is scripted to respond
|
||||||
|
if (!objectTouchable && !part.IsRoot)
|
||||||
|
objectTouchable = hasTouchEvents(part.ParentGroup.RootPart);
|
||||||
|
if (!objectTouchable)
|
||||||
|
return false;
|
||||||
|
// Set up the surface args as if the touch is from a client that does not support this
|
||||||
|
SurfaceTouchEventArgs surfaceArgs = new SurfaceTouchEventArgs();
|
||||||
|
surfaceArgs.FaceIndex = -1; // TOUCH_INVALID_FACE
|
||||||
|
surfaceArgs.Binormal = Vector3.Zero; // TOUCH_INVALID_VECTOR
|
||||||
|
surfaceArgs.Normal = Vector3.Zero; // TOUCH_INVALID_VECTOR
|
||||||
|
surfaceArgs.STCoord = new Vector3(-1.0f, -1.0f, 0.0f); // TOUCH_INVALID_TEXCOORD
|
||||||
|
surfaceArgs.UVCoord = surfaceArgs.STCoord; // TOUCH_INVALID_TEXCOORD
|
||||||
|
List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
|
||||||
|
touchArgs.Add(surfaceArgs);
|
||||||
|
Vector3 offset = part.OffsetPosition * -1.0f;
|
||||||
|
if (OnGrabObject == null)
|
||||||
|
return false;
|
||||||
|
OnGrabObject(part.LocalId, offset, this, touchArgs);
|
||||||
|
if (OnGrabUpdate != null)
|
||||||
|
OnGrabUpdate(part.UUID, offset, part.ParentGroup.RootPart.GroupPosition, this, touchArgs);
|
||||||
|
if (OnDeGrabObject != null)
|
||||||
|
OnDeGrabObject(part.LocalId, this, touchArgs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool hasTouchEvents(SceneObjectPart part)
|
||||||
|
{
|
||||||
|
if ((part.ScriptEvents & scriptEvents.touch) != 0 ||
|
||||||
|
(part.ScriptEvents & scriptEvents.touch_start) != 0 ||
|
||||||
|
(part.ScriptEvents & scriptEvents.touch_end) != 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void InstantMessage(UUID target, string message)
|
public void InstantMessage(UUID target, string message)
|
||||||
{
|
{
|
||||||
OnInstantMessage(this, new GridInstantMessage(m_scene,
|
OnInstantMessage(this, new GridInstantMessage(m_scene,
|
||||||
|
@ -153,6 +192,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
|
|
||||||
private void SendOnChatFromClient(int channel, string message, ChatTypeEnum chatType)
|
private void SendOnChatFromClient(int channel, string message, ChatTypeEnum chatType)
|
||||||
{
|
{
|
||||||
|
if (channel == 0)
|
||||||
|
{
|
||||||
|
message = message.Trim();
|
||||||
|
if (string.IsNullOrEmpty(message))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
OSChatMessage chatFromClient = new OSChatMessage();
|
OSChatMessage chatFromClient = new OSChatMessage();
|
||||||
chatFromClient.Channel = channel;
|
chatFromClient.Channel = channel;
|
||||||
chatFromClient.From = Name;
|
chatFromClient.From = Name;
|
||||||
|
|
|
@ -306,6 +306,16 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Touch(UUID agentID, UUID objectID)
|
||||||
|
{
|
||||||
|
lock (m_avatars)
|
||||||
|
{
|
||||||
|
if (m_avatars.ContainsKey(agentID))
|
||||||
|
return m_avatars[agentID].Touch(objectID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public UUID GetOwner(UUID agentID)
|
public UUID GetOwner(UUID agentID)
|
||||||
{
|
{
|
||||||
lock (m_avatars)
|
lock (m_avatars)
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class BSCharacter : PhysicsActor
|
||||||
private float _buoyancy;
|
private float _buoyancy;
|
||||||
|
|
||||||
private int _subscribedEventsMs = 0;
|
private int _subscribedEventsMs = 0;
|
||||||
private int _lastCollisionTime = 0;
|
private int _nextCollisionOkTime = 0;
|
||||||
|
|
||||||
private Vector3 _PIDTarget;
|
private Vector3 _PIDTarget;
|
||||||
private bool _usePID;
|
private bool _usePID;
|
||||||
|
@ -360,17 +360,22 @@ public class BSCharacter : PhysicsActor
|
||||||
}
|
}
|
||||||
//m_lastUpdateSent = false;
|
//m_lastUpdateSent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddAngularForce(Vector3 force, bool pushforce) {
|
public override void AddAngularForce(Vector3 force, bool pushforce) {
|
||||||
}
|
}
|
||||||
public override void SetMomentum(Vector3 momentum) {
|
public override void SetMomentum(Vector3 momentum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn on collision events at a rate no faster than one every the given milliseconds
|
||||||
public override void SubscribeEvents(int ms) {
|
public override void SubscribeEvents(int ms) {
|
||||||
_subscribedEventsMs = ms;
|
_subscribedEventsMs = ms;
|
||||||
_lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen
|
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen
|
||||||
}
|
}
|
||||||
|
// Stop collision events
|
||||||
public override void UnSubscribeEvents() {
|
public override void UnSubscribeEvents() {
|
||||||
_subscribedEventsMs = 0;
|
_subscribedEventsMs = 0;
|
||||||
}
|
}
|
||||||
|
// Return 'true' if someone has subscribed to events
|
||||||
public override bool SubscribedEvents() {
|
public override bool SubscribedEvents() {
|
||||||
return (_subscribedEventsMs > 0);
|
return (_subscribedEventsMs > 0);
|
||||||
}
|
}
|
||||||
|
@ -386,47 +391,57 @@ public class BSCharacter : PhysicsActor
|
||||||
_mass = _density * _avatarVolume;
|
_mass = _density * _avatarVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set to 'true' if the individual changed items should be checked
|
||||||
|
// (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties)
|
||||||
|
const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false;
|
||||||
|
|
||||||
// The physics engine says that properties have updated. Update same and inform
|
// The physics engine says that properties have updated. Update same and inform
|
||||||
// the world that things have changed.
|
// the world that things have changed.
|
||||||
public void UpdateProperties(EntityProperties entprop)
|
public void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) {
|
||||||
// we assign to the local variables so the normal set action does not happen
|
// we assign to the local variables so the normal set action does not happen
|
||||||
if (_position != entprop.Position)
|
if (_position != entprop.Position) {
|
||||||
{
|
|
||||||
_position = entprop.Position;
|
_position = entprop.Position;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (_orientation != entprop.Rotation)
|
if (_orientation != entprop.Rotation) {
|
||||||
{
|
|
||||||
_orientation = entprop.Rotation;
|
_orientation = entprop.Rotation;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (_velocity != entprop.Velocity)
|
if (_velocity != entprop.Velocity) {
|
||||||
{
|
|
||||||
_velocity = entprop.Velocity;
|
_velocity = entprop.Velocity;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (_acceleration != entprop.Acceleration)
|
if (_acceleration != entprop.Acceleration) {
|
||||||
{
|
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (_rotationalVelocity != entprop.RotationalVelocity)
|
if (_rotationalVelocity != entprop.RotationalVelocity) {
|
||||||
{
|
|
||||||
_rotationalVelocity = entprop.RotationalVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed) {
|
||||||
{
|
|
||||||
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
|
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
|
||||||
// Avatar movement is not done by generating this event. There is a system that
|
// Avatar movement is not done by generating this event. There is code in the heartbeat
|
||||||
// checks for avatar updates each heartbeat loop.
|
// loop that updates avatars.
|
||||||
|
// base.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_position = entprop.Position;
|
||||||
|
_orientation = entprop.Rotation;
|
||||||
|
_velocity = entprop.Velocity;
|
||||||
|
_acceleration = entprop.Acceleration;
|
||||||
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
// base.RequestPhysicsterseUpdate();
|
// base.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the scene when a collision with this object is reported
|
// Called by the scene when a collision with this object is reported
|
||||||
|
// The collision, if it should be reported to the character, is placed in a collection
|
||||||
|
// that will later be sent to the simulator when SendCollisions() is called.
|
||||||
CollisionEventUpdate collisionCollection = null;
|
CollisionEventUpdate collisionCollection = null;
|
||||||
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||||
{
|
{
|
||||||
|
@ -440,29 +455,34 @@ public class BSCharacter : PhysicsActor
|
||||||
}
|
}
|
||||||
|
|
||||||
// throttle collisions to the rate specified in the subscription
|
// throttle collisions to the rate specified in the subscription
|
||||||
if (_subscribedEventsMs == 0) return; // don't want collisions
|
if (_subscribedEventsMs != 0) {
|
||||||
int nowTime = _scene.SimulationNowTime;
|
int nowTime = _scene.SimulationNowTime;
|
||||||
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
|
if (nowTime >= _nextCollisionOkTime) {
|
||||||
_lastCollisionTime = nowTime;
|
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||||
|
|
||||||
if (collisionCollection == null)
|
if (collisionCollection == null)
|
||||||
collisionCollection = new CollisionEventUpdate();
|
collisionCollection = new CollisionEventUpdate();
|
||||||
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SendCollisions()
|
public void SendCollisions()
|
||||||
{
|
{
|
||||||
// if (collisionCollection != null)
|
/*
|
||||||
// {
|
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||||
// base.SendCollisionUpdate(collisionCollection);
|
{
|
||||||
// collisionCollection = null;
|
base.SendCollisionUpdate(collisionCollection);
|
||||||
// }
|
collisionCollection = null;
|
||||||
|
}
|
||||||
|
*/
|
||||||
// Kludge to make a collision call even if there are no collisions.
|
// Kludge to make a collision call even if there are no collisions.
|
||||||
// This causes the avatar animation to get updated.
|
// This causes the avatar animation to get updated.
|
||||||
if (collisionCollection == null)
|
if (collisionCollection == null)
|
||||||
collisionCollection = new CollisionEventUpdate();
|
collisionCollection = new CollisionEventUpdate();
|
||||||
base.SendCollisionUpdate(collisionCollection);
|
base.SendCollisionUpdate(collisionCollection);
|
||||||
collisionCollection = null;
|
collisionCollection.Clear();
|
||||||
|
// End kludge
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,14 @@ using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim.
|
||||||
|
/// This module interfaces to an unmanaged C++ library which makes the
|
||||||
|
/// actual calls into the Bullet physics engine.
|
||||||
|
/// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/.
|
||||||
|
/// The unmanaged library is compiled and linked statically with Bullet
|
||||||
|
/// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit).
|
||||||
|
/// </summary>
|
||||||
public class BSPlugin : IPhysicsPlugin
|
public class BSPlugin : IPhysicsPlugin
|
||||||
{
|
{
|
||||||
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
@ -53,6 +61,9 @@ public class BSPlugin : IPhysicsPlugin
|
||||||
{
|
{
|
||||||
if (Util.IsWindows())
|
if (Util.IsWindows())
|
||||||
Util.LoadArchSpecificWindowsDll("BulletSim.dll");
|
Util.LoadArchSpecificWindowsDll("BulletSim.dll");
|
||||||
|
// If not Windows, loading is performed by the
|
||||||
|
// Mono loader as specified in
|
||||||
|
// "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
|
||||||
|
|
||||||
_mScene = new BSScene(sceneIdentifier);
|
_mScene = new BSScene(sceneIdentifier);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
private BSPrim _parentPrim;
|
private BSPrim _parentPrim;
|
||||||
|
|
||||||
private int _subscribedEventsMs = 0;
|
private int _subscribedEventsMs = 0;
|
||||||
private int _lastCollisionTime = 0;
|
private int _nextCollisionOkTime = 0;
|
||||||
long _collidingStep;
|
long _collidingStep;
|
||||||
long _collidingGroundStep;
|
long _collidingGroundStep;
|
||||||
|
|
||||||
|
@ -597,7 +597,8 @@ public sealed class BSPrim : PhysicsActor
|
||||||
}
|
}
|
||||||
public override void SubscribeEvents(int ms) {
|
public override void SubscribeEvents(int ms) {
|
||||||
_subscribedEventsMs = ms;
|
_subscribedEventsMs = ms;
|
||||||
_lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen
|
// make sure first collision happens
|
||||||
|
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
|
||||||
}
|
}
|
||||||
public override void UnSubscribeEvents() {
|
public override void UnSubscribeEvents() {
|
||||||
_subscribedEventsMs = 0;
|
_subscribedEventsMs = 0;
|
||||||
|
@ -1338,23 +1339,27 @@ public sealed class BSPrim : PhysicsActor
|
||||||
_collidingGroundStep = _scene.SimulationStep;
|
_collidingGroundStep = _scene.SimulationStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_subscribedEventsMs == 0) return; // nothing in the object is waiting for collision events
|
// if someone is subscribed to collision events....
|
||||||
|
if (_subscribedEventsMs != 0) {
|
||||||
// throttle the collisions to the number of milliseconds specified in the subscription
|
// throttle the collisions to the number of milliseconds specified in the subscription
|
||||||
int nowTime = _scene.SimulationNowTime;
|
int nowTime = _scene.SimulationNowTime;
|
||||||
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
|
if (nowTime >= _nextCollisionOkTime) {
|
||||||
_lastCollisionTime = nowTime;
|
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||||
|
|
||||||
if (collisionCollection == null)
|
if (collisionCollection == null)
|
||||||
collisionCollection = new CollisionEventUpdate();
|
collisionCollection = new CollisionEventUpdate();
|
||||||
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The scene is telling us it's time to pass our collected collisions into the simulator
|
||||||
public void SendCollisions()
|
public void SendCollisions()
|
||||||
{
|
{
|
||||||
if (collisionCollection != null)
|
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||||
{
|
{
|
||||||
base.SendCollisionUpdate(collisionCollection);
|
base.SendCollisionUpdate(collisionCollection);
|
||||||
collisionCollection = null;
|
collisionCollection.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ using OpenSim.Region.Framework;
|
||||||
// Should prim.link() and prim.delink() membership checking happen at taint time?
|
// Should prim.link() and prim.delink() membership checking happen at taint time?
|
||||||
// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
|
// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
|
||||||
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
|
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
|
||||||
|
// Use collision masks for collision with terrain and phantom objects
|
||||||
// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
|
// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
|
||||||
// Implement LockAngularMotion
|
// Implement LockAngularMotion
|
||||||
// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
|
// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
|
||||||
|
@ -62,9 +63,6 @@ using OpenSim.Region.Framework;
|
||||||
// Multiple contact points on collision?
|
// Multiple contact points on collision?
|
||||||
// See code in ode::near... calls to collision_accounting_events()
|
// See code in ode::near... calls to collision_accounting_events()
|
||||||
// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
|
// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
|
||||||
// Use collision masks for collision with terrain and phantom objects
|
|
||||||
// Figure out how to not allocate a new Dictionary and List for every collision
|
|
||||||
// in BSPrim.Collide() and BSCharacter.Collide(). Can the same ones be reused?
|
|
||||||
// Raycast
|
// Raycast
|
||||||
//
|
//
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
@ -405,6 +403,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// prevent simulation until we've been initialized
|
// prevent simulation until we've been initialized
|
||||||
if (!m_initialized) return 10.0f;
|
if (!m_initialized) return 10.0f;
|
||||||
|
|
||||||
|
long simulateStartTime = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
// update the prim states while we know the physics engine is not busy
|
// update the prim states while we know the physics engine is not busy
|
||||||
ProcessTaints();
|
ProcessTaints();
|
||||||
|
|
||||||
|
@ -437,13 +437,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator.
|
// The above SendCollision's batch up the collisions on the objects.
|
||||||
|
// Now push the collisions into the simulator.
|
||||||
foreach (BSPrim bsp in m_primsWithCollisions)
|
foreach (BSPrim bsp in m_primsWithCollisions)
|
||||||
bsp.SendCollisions();
|
bsp.SendCollisions();
|
||||||
m_primsWithCollisions.Clear();
|
m_primsWithCollisions.Clear();
|
||||||
|
|
||||||
|
// This is a kludge to get avatar movement updated.
|
||||||
|
// Don't send collisions only if there were collisions -- send everytime.
|
||||||
|
// ODE sends collisions even if there are none and this is used to update
|
||||||
|
// avatar animations and stuff.
|
||||||
// foreach (BSCharacter bsc in m_avatarsWithCollisions)
|
// foreach (BSCharacter bsc in m_avatarsWithCollisions)
|
||||||
// bsc.SendCollisions();
|
// bsc.SendCollisions();
|
||||||
// This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any
|
|
||||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
||||||
kvp.Value.SendCollisions();
|
kvp.Value.SendCollisions();
|
||||||
m_avatarsWithCollisions.Clear();
|
m_avatarsWithCollisions.Clear();
|
||||||
|
@ -465,10 +470,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
if (m_avatars.TryGetValue(entprop.ID, out actor))
|
if (m_avatars.TryGetValue(entprop.ID, out actor))
|
||||||
{
|
{
|
||||||
actor.UpdateProperties(entprop);
|
actor.UpdateProperties(entprop);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If enabled, call into the physics engine to dump statistics
|
||||||
if (m_detailedStatsStep > 0)
|
if (m_detailedStatsStep > 0)
|
||||||
{
|
{
|
||||||
if ((m_simulationStep % m_detailedStatsStep) == 0)
|
if ((m_simulationStep % m_detailedStatsStep) == 0)
|
||||||
|
@ -477,6 +484,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is a waste since the outside routine also calcuates the physics simulation
|
||||||
|
// period. TODO: There should be a way of computing physics frames from simulator computation.
|
||||||
|
// long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
|
||||||
|
// return (timeStep * (float)simulateTotalTime);
|
||||||
|
|
||||||
// TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation.
|
// TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation.
|
||||||
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
|
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
|
||||||
}
|
}
|
||||||
|
@ -528,6 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
public override void SetWaterLevel(float baseheight)
|
public override void SetWaterLevel(float baseheight)
|
||||||
{
|
{
|
||||||
m_waterLevel = baseheight;
|
m_waterLevel = baseheight;
|
||||||
|
// TODO: pass to physics engine so things will float?
|
||||||
}
|
}
|
||||||
public float GetWaterLevel()
|
public float GetWaterLevel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -2725,6 +2725,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num)
|
||||||
|
{
|
||||||
|
CheckThreatLevel(ThreatLevel.High, "osNpcTouch");
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
INPCModule module = World.RequestModuleInterface<INPCModule>();
|
||||||
|
int linkNum = link_num.value;
|
||||||
|
if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS))
|
||||||
|
{
|
||||||
|
UUID npcId;
|
||||||
|
if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID))
|
||||||
|
return;
|
||||||
|
SceneObjectPart part = null;
|
||||||
|
UUID objectId;
|
||||||
|
if (UUID.TryParse(LSL_String.ToString(object_key), out objectId))
|
||||||
|
part = World.GetSceneObjectPart(objectId);
|
||||||
|
if (part == null)
|
||||||
|
return;
|
||||||
|
if (linkNum != ScriptBaseClass.LINK_THIS)
|
||||||
|
{
|
||||||
|
if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT)
|
||||||
|
{ // 0 and 1 are treated as root, find the root if the current part isnt it
|
||||||
|
if (!part.IsRoot)
|
||||||
|
part = part.ParentGroup.RootPart;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Find the prim with the given link number if not found then fail silently
|
||||||
|
part = part.ParentGroup.GetLinkNumPart(linkNum);
|
||||||
|
if (part == null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.Touch(npcId, part.UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save the current appearance of the script owner permanently to the named notecard.
|
/// Save the current appearance of the script owner permanently to the named notecard.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -3203,13 +3238,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory");
|
CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory");
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
|
ForceAttachToAvatarFromInventory(m_host.OwnerID, itemName, attachmentPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
|
||||||
|
{
|
||||||
|
CheckThreatLevel(ThreatLevel.Severe, "osForceAttachToOtherAvatarFromInventory");
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
|
UUID avatarId;
|
||||||
|
|
||||||
|
if (!UUID.TryParse(rawAvatarId, out avatarId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ForceAttachToAvatarFromInventory(avatarId, itemName, attachmentPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForceAttachToAvatarFromInventory(UUID avatarId, string itemName, int attachmentPoint)
|
||||||
|
{
|
||||||
IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
|
IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
|
||||||
|
|
||||||
if (attachmentsModule == null)
|
if (attachmentsModule == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_host.AddScriptLPS(1);
|
|
||||||
|
|
||||||
InitLSL();
|
InitLSL();
|
||||||
|
|
||||||
TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
|
TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
|
||||||
|
@ -3232,7 +3286,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
|
ScenePresence sp = World.GetScenePresence(avatarId);
|
||||||
|
|
||||||
if (sp == null)
|
if (sp == null)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -101,18 +101,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||||
// Attachment commands
|
// Attachment commands
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attach the object containing this script to the avatar that owns it without checking for PERMISSION_ATTACH
|
/// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
|
/// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
|
||||||
void osForceAttachToAvatar(int attachment);
|
void osForceAttachToAvatar(int attachment);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attach the inventory item in the object containing this script to the avatar that owns it without checking for PERMISSION_ATTACH
|
/// Attach an inventory item in the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Nothing happens if the owner is not in the region.
|
||||||
|
/// </remarks>
|
||||||
/// <param name='itemName'>Tha name of the item. If this is not found then a warning is said to the owner</param>
|
/// <param name='itemName'>Tha name of the item. If this is not found then a warning is said to the owner</param>
|
||||||
/// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
|
/// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
|
||||||
void osForceAttachToAvatarFromInventory(string itemName, int attachment);
|
void osForceAttachToAvatarFromInventory(string itemName, int attachment);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attach an inventory item in the object containing this script to any avatar in the region without asking for PERMISSION_ATTACH
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Nothing happens if the avatar is not in the region.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name='rawAvatarId'>The UUID of the avatar to which to attach. Nothing happens if this is not a UUID</para>
|
||||||
|
/// <param name='itemName'>The name of the item. If this is not found then a warning is said to the owner</param>
|
||||||
|
/// <param name='attachment'>The attachment point. For example, ATTACH_CHEST</param>
|
||||||
|
void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Detach the object containing this script from the avatar it is attached to without checking for PERMISSION_ATTACH
|
/// Detach the object containing this script from the avatar it is attached to without checking for PERMISSION_ATTACH
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -231,6 +245,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||||
void osNpcRemove(key npc);
|
void osNpcRemove(key npc);
|
||||||
void osNpcPlayAnimation(LSL_Key npc, string animation);
|
void osNpcPlayAnimation(LSL_Key npc, string animation);
|
||||||
void osNpcStopAnimation(LSL_Key npc, string animation);
|
void osNpcStopAnimation(LSL_Key npc, string animation);
|
||||||
|
void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num);
|
||||||
void osNpcWhisper(key npc, int channel, string message);
|
void osNpcWhisper(key npc, int channel, string message);
|
||||||
|
|
||||||
LSL_Key osOwnerSaveAppearance(string notecard);
|
LSL_Key osOwnerSaveAppearance(string notecard);
|
||||||
|
|
|
@ -301,6 +301,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
m_OSSL_Functions.osForceAttachToAvatarFromInventory(itemName, attachmentPoint);
|
m_OSSL_Functions.osForceAttachToAvatarFromInventory(itemName, attachmentPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
|
||||||
|
{
|
||||||
|
m_OSSL_Functions.osForceAttachToOtherAvatarFromInventory(rawAvatarId, itemName, attachmentPoint);
|
||||||
|
}
|
||||||
|
|
||||||
public void osForceDetachFromAvatar()
|
public void osForceDetachFromAvatar()
|
||||||
{
|
{
|
||||||
m_OSSL_Functions.osForceDetachFromAvatar();
|
m_OSSL_Functions.osForceDetachFromAvatar();
|
||||||
|
@ -626,6 +631,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
m_OSSL_Functions.osNpcWhisper(npc, channel, message);
|
m_OSSL_Functions.osNpcWhisper(npc, channel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num)
|
||||||
|
{
|
||||||
|
m_OSSL_Functions.osNpcTouch(npcLSL_Key, object_key, link_num);
|
||||||
|
}
|
||||||
|
|
||||||
public LSL_Key osOwnerSaveAppearance(string notecard)
|
public LSL_Key osOwnerSaveAppearance(string notecard)
|
||||||
{
|
{
|
||||||
return m_OSSL_Functions.osOwnerSaveAppearance(notecard);
|
return m_OSSL_Functions.osOwnerSaveAppearance(notecard);
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
/// Test creation of an NPC where the appearance data comes from a notecard
|
/// Test creation of an NPC where the appearance data comes from a notecard
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void TestOsNpcCreateFromNotecard()
|
public void TestOsNpcCreateUsingAppearanceFromNotecard()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// log4net.Config.XmlConfigurator.Configure();
|
// log4net.Config.XmlConfigurator.Configure();
|
||||||
|
@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
|
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
||||||
sp.Appearance.AvatarHeight = newHeight;
|
sp.Appearance.AvatarHeight = newHeight;
|
||||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId);
|
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
|
||||||
SceneObjectPart part = so.RootPart;
|
SceneObjectPart part = so.RootPart;
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
|
@ -114,10 +114,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
/// Test creation of an NPC where the appearance data comes from an avatar already in the region.
|
/// Test creation of an NPC where the appearance data comes from an avatar already in the region.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void TestOsNpcCreateFromAvatar()
|
public void TestOsNpcCreateUsingAppearanceFromAvatar()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// log4net.Config.XmlConfigurator.Configure();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
// Store an avatar with a different height from default in a notecard.
|
// Store an avatar with a different height from default in a notecard.
|
||||||
UUID userId = TestHelpers.ParseTail(0x1);
|
UUID userId = TestHelpers.ParseTail(0x1);
|
||||||
|
@ -125,7 +125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
|
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
||||||
sp.Appearance.AvatarHeight = newHeight;
|
sp.Appearance.AvatarHeight = newHeight;
|
||||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId);
|
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
|
||||||
SceneObjectPart part = so.RootPart;
|
SceneObjectPart part = so.RootPart;
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
|
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
||||||
sp.Appearance.AvatarHeight = newHeight;
|
sp.Appearance.AvatarHeight = newHeight;
|
||||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId);
|
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
|
||||||
SceneObjectPart part = so.RootPart;
|
SceneObjectPart part = so.RootPart;
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
|
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId);
|
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId);
|
||||||
sp.Appearance.AvatarHeight = newHeight;
|
sp.Appearance.AvatarHeight = newHeight;
|
||||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId);
|
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId, 0x10);
|
||||||
SceneObjectPart part = so.RootPart;
|
SceneObjectPart part = so.RootPart;
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
{
|
{
|
||||||
osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint);
|
osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
exceptionCaught = true;
|
exceptionCaught = true;
|
||||||
}
|
}
|
||||||
|
@ -174,5 +174,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
|
List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
|
||||||
Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0));
|
Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOsForceAttachToOtherAvatarFromInventory()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
string taskInvObjItemName = "sphere";
|
||||||
|
UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000");
|
||||||
|
AttachmentPoint attachPoint = AttachmentPoint.Chin;
|
||||||
|
|
||||||
|
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "one", 0x1, "pass");
|
||||||
|
UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "two", 0x2, "pass");
|
||||||
|
|
||||||
|
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1);
|
||||||
|
SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
|
||||||
|
TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
|
||||||
|
|
||||||
|
new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem);
|
||||||
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
|
osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem);
|
||||||
|
|
||||||
|
// Create an object embedded inside the first
|
||||||
|
TaskInventoryHelpers.AddSceneObject(m_scene, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID);
|
||||||
|
|
||||||
|
ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2);
|
||||||
|
|
||||||
|
osslApi.osForceAttachToOtherAvatarFromInventory(sp2.UUID.ToString(), taskInvObjItemName, (int)attachPoint);
|
||||||
|
|
||||||
|
// Check scene presence status
|
||||||
|
Assert.That(sp.HasAttachments(), Is.False);
|
||||||
|
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||||
|
Assert.That(attachments.Count, Is.EqualTo(0));
|
||||||
|
|
||||||
|
Assert.That(sp2.HasAttachments(), Is.True);
|
||||||
|
List<SceneObjectGroup> attachments2 = sp2.GetAttachments();
|
||||||
|
Assert.That(attachments2.Count, Is.EqualTo(1));
|
||||||
|
SceneObjectGroup attSo = attachments2[0];
|
||||||
|
Assert.That(attSo.Name, Is.EqualTo(taskInvObjItemName));
|
||||||
|
Assert.That(attSo.OwnerID, Is.EqualTo(ua2.PrincipalID));
|
||||||
|
Assert.That(attSo.AttachmentPoint, Is.EqualTo((uint)attachPoint));
|
||||||
|
Assert.That(attSo.IsAttachment);
|
||||||
|
Assert.That(attSo.UsesPhysics, Is.False);
|
||||||
|
Assert.That(attSo.IsTemporary, Is.False);
|
||||||
|
|
||||||
|
// Check appearance status
|
||||||
|
List<AvatarAttachment> attachmentsInAppearance = sp.Appearance.GetAttachments();
|
||||||
|
Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0));
|
||||||
|
|
||||||
|
List<AvatarAttachment> attachmentsInAppearance2 = sp2.Appearance.GetAttachments();
|
||||||
|
Assert.That(attachmentsInAppearance2.Count, Is.EqualTo(1));
|
||||||
|
Assert.That(sp2.Appearance.GetAttachpoint(attachmentsInAppearance2[0].ItemID), Is.EqualTo((uint)attachPoint));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -97,11 +97,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
||||||
sp.Appearance.AvatarHeight = newHeight;
|
sp.Appearance.AvatarHeight = newHeight;
|
||||||
|
|
||||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId);
|
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
|
||||||
SceneObjectPart part = so.RootPart;
|
SceneObjectPart part = so.RootPart;
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId);
|
SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId, 0x20);
|
||||||
SceneObjectPart otherPart = otherSo.RootPart;
|
SceneObjectPart otherPart = otherSo.RootPart;
|
||||||
m_scene.AddSceneObject(otherSo);
|
m_scene.AddSceneObject(otherSo);
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
|
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
|
||||||
sp.Appearance.AvatarHeight = newHeight;
|
sp.Appearance.AvatarHeight = newHeight;
|
||||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId);
|
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
|
||||||
SceneObjectPart part = so.RootPart;
|
SceneObjectPart part = so.RootPart;
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
|
|
|
@ -1662,7 +1662,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
{
|
{
|
||||||
IScriptInstance instance = GetInstance(itemID);
|
IScriptInstance instance = GetInstance(itemID);
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
instance.Stop(0);
|
{
|
||||||
|
// Give the script some time to finish processing its last event. Simply aborting the script thread can
|
||||||
|
// cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
|
||||||
|
instance.Stop(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DetectParams GetDetectParams(UUID itemID, int idx)
|
public DetectParams GetDetectParams(UUID itemID, int idx)
|
||||||
|
|
|
@ -412,26 +412,49 @@ namespace OpenSim.Tests.Common
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static AgentCircuitData GenerateAgentData(UUID agentId)
|
public static AgentCircuitData GenerateAgentData(UUID agentId)
|
||||||
{
|
{
|
||||||
string firstName = "testfirstname";
|
AgentCircuitData acd = GenerateCommonAgentData();
|
||||||
|
|
||||||
AgentCircuitData agentData = new AgentCircuitData();
|
acd.AgentID = agentId;
|
||||||
agentData.AgentID = agentId;
|
acd.firstname = "testfirstname";
|
||||||
agentData.firstname = firstName;
|
acd.lastname = "testlastname";
|
||||||
agentData.lastname = "testlastname";
|
acd.ServiceURLs = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
return acd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate some standard agent connection data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agentId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static AgentCircuitData GenerateAgentData(UserAccount ua)
|
||||||
|
{
|
||||||
|
AgentCircuitData acd = GenerateCommonAgentData();
|
||||||
|
|
||||||
|
acd.AgentID = ua.PrincipalID;
|
||||||
|
acd.firstname = ua.FirstName;
|
||||||
|
acd.lastname = ua.LastName;
|
||||||
|
acd.ServiceURLs = ua.ServiceURLs;
|
||||||
|
|
||||||
|
return acd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AgentCircuitData GenerateCommonAgentData()
|
||||||
|
{
|
||||||
|
AgentCircuitData acd = new AgentCircuitData();
|
||||||
|
|
||||||
// XXX: Sessions must be unique, otherwise one presence can overwrite another in NullPresenceData.
|
// XXX: Sessions must be unique, otherwise one presence can overwrite another in NullPresenceData.
|
||||||
agentData.SessionID = UUID.Random();
|
acd.SessionID = UUID.Random();
|
||||||
agentData.SecureSessionID = UUID.Random();
|
acd.SecureSessionID = UUID.Random();
|
||||||
|
|
||||||
agentData.circuitcode = 123;
|
acd.circuitcode = 123;
|
||||||
agentData.BaseFolder = UUID.Zero;
|
acd.BaseFolder = UUID.Zero;
|
||||||
agentData.InventoryFolder = UUID.Zero;
|
acd.InventoryFolder = UUID.Zero;
|
||||||
agentData.startpos = Vector3.Zero;
|
acd.startpos = Vector3.Zero;
|
||||||
agentData.CapsPath = "http://wibble.com";
|
acd.CapsPath = "http://wibble.com";
|
||||||
agentData.ServiceURLs = new Dictionary<string, object>();
|
acd.Appearance = new AvatarAppearance();
|
||||||
agentData.Appearance = new AvatarAppearance();
|
|
||||||
|
|
||||||
return agentData;
|
return acd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -440,6 +463,9 @@ namespace OpenSim.Tests.Common
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This can be used for tests where there is only one region or where there are multiple non-neighbour regions
|
/// This can be used for tests where there is only one region or where there are multiple non-neighbour regions
|
||||||
/// and teleport doesn't take place.
|
/// and teleport doesn't take place.
|
||||||
|
///
|
||||||
|
/// XXX: Use the version of this method that takes the UserAccount structure wherever possible - this will
|
||||||
|
/// make the agent circuit data (e.g. first, lastname) consistent with the user account data.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="scene"></param>
|
/// <param name="scene"></param>
|
||||||
/// <param name="agentId"></param>
|
/// <param name="agentId"></param>
|
||||||
|
@ -452,6 +478,10 @@ namespace OpenSim.Tests.Common
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test
|
/// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// XXX: Use the version of this method that takes the UserAccount structure wherever possible - this will
|
||||||
|
/// make the agent circuit data (e.g. first, lastname) consistent with the user account data.
|
||||||
|
/// </remarks>
|
||||||
/// <param name="scene"></param>
|
/// <param name="scene"></param>
|
||||||
/// <param name="agentId"></param>
|
/// <param name="agentId"></param>
|
||||||
/// <param name="sceneManager"></param>
|
/// <param name="sceneManager"></param>
|
||||||
|
@ -461,6 +491,17 @@ namespace OpenSim.Tests.Common
|
||||||
return AddScenePresence(scene, GenerateAgentData(agentId), sceneManager);
|
return AddScenePresence(scene, GenerateAgentData(agentId), sceneManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a root agent.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scene"></param>
|
||||||
|
/// <param name="ua"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ScenePresence AddScenePresence(Scene scene, UserAccount ua)
|
||||||
|
{
|
||||||
|
return AddScenePresence(scene, GenerateAgentData(ua));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a root agent.
|
/// Add a root agent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -606,14 +647,31 @@ namespace OpenSim.Tests.Common
|
||||||
/// Create a scene object but do not add it to the scene.
|
/// Create a scene object but do not add it to the scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// UUID always starts at 00000000-0000-0000-0000-000000000001
|
/// UUID always starts at 00000000-0000-0000-0000-000000000001. For some purposes, (e.g. serializing direct
|
||||||
|
/// to another object's inventory) we do not need a scene unique ID. So it would be better to add the
|
||||||
|
/// UUID when we actually add an object to a scene rather than on creation.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="parts">The number of parts that should be in the scene object</param>
|
/// <param name="parts">The number of parts that should be in the scene object</param>
|
||||||
/// <param name="ownerId"></param>
|
/// <param name="ownerId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId)
|
public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId)
|
||||||
{
|
{
|
||||||
return CreateSceneObject(parts, ownerId, "", 0x1);
|
return CreateSceneObject(parts, ownerId, 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a scene object but do not add it to the scene.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parts">The number of parts that should be in the scene object</param>
|
||||||
|
/// <param name="ownerId"></param>
|
||||||
|
/// <param name="uuidTail">
|
||||||
|
/// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}"
|
||||||
|
/// will be given to the root part, and incremented for each part thereafter.
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, int uuidTail)
|
||||||
|
{
|
||||||
|
return CreateSceneObject(parts, ownerId, "", uuidTail);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -139,6 +139,15 @@ namespace OpenSim.Tests.Common
|
||||||
return ua;
|
return ua;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UserAccount CreateUserWithInventory(
|
||||||
|
Scene scene, string firstName, string lastName, int userId, string pw)
|
||||||
|
{
|
||||||
|
UserAccount ua
|
||||||
|
= new UserAccount(TestHelpers.ParseTail(userId)) { FirstName = firstName, LastName = lastName };
|
||||||
|
CreateUserWithInventory(scene, ua, pw);
|
||||||
|
return ua;
|
||||||
|
}
|
||||||
|
|
||||||
public static void CreateUserWithInventory(Scene scene, UserAccount ua, string pw)
|
public static void CreateUserWithInventory(Scene scene, UserAccount ua, string pw)
|
||||||
{
|
{
|
||||||
// FIXME: This should really be set up by UserAccount itself
|
// FIXME: This should really be set up by UserAccount itself
|
||||||
|
|
|
@ -61,17 +61,20 @@
|
||||||
;; Place to create a PID file
|
;; Place to create a PID file
|
||||||
; PIDFile = "/tmp/my.pid"
|
; PIDFile = "/tmp/my.pid"
|
||||||
|
|
||||||
|
;# {region_info_source} {} {Where to load region from?} {filesystem web} filesystem
|
||||||
;; Determine where OpenSimulator looks for the files which tell it
|
;; Determine where OpenSimulator looks for the files which tell it
|
||||||
;; which regions to server
|
;; which regions to server
|
||||||
;; Default is "filesystem"
|
;; Default is "filesystem"
|
||||||
; region_info_source = "filesystem"
|
; region_info_source = "filesystem"
|
||||||
; region_info_source = "web"
|
; region_info_source = "web"
|
||||||
|
|
||||||
|
;# {regionload_regionsdir} {region_info_source} {Location of file?} {} Regions
|
||||||
;; Determines where the region XML files are stored if you are loading
|
;; Determines where the region XML files are stored if you are loading
|
||||||
;; these from the filesystem.
|
;; these from the filesystem.
|
||||||
;; Defaults to bin/Regions in your OpenSimulator installation directory
|
;; Defaults to bin/Regions in your OpenSimulator installation directory
|
||||||
; regionload_regionsdir="C:\somewhere\xmlfiles\"
|
; regionload_regionsdir="C:\somewhere\xmlfiles\"
|
||||||
|
|
||||||
|
;# {regionload_webserver_url} {region_info_source} {URL to load region from?} {}
|
||||||
;; Determines the page from which regions xml is retrieved if you are
|
;; Determines the page from which regions xml is retrieved if you are
|
||||||
;; loading these from the web.
|
;; loading these from the web.
|
||||||
;; The XML here has the same format as it does on the filesystem
|
;; The XML here has the same format as it does on the filesystem
|
||||||
|
@ -92,6 +95,7 @@
|
||||||
;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file.
|
;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file.
|
||||||
; PhysicalPrimMax = 10
|
; PhysicalPrimMax = 10
|
||||||
|
|
||||||
|
;# {ClampPrimSize} {} {Clamp viewer rezzed prims to max sizes?} {true false} false
|
||||||
;; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
|
;; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
|
||||||
;; This can be overriden in the region config file.
|
;; This can be overriden in the region config file.
|
||||||
; ClampPrimSize = false
|
; ClampPrimSize = false
|
||||||
|
@ -117,6 +121,7 @@
|
||||||
;; This will likely break them
|
;; This will likely break them
|
||||||
; CombineContiguousRegions = false
|
; CombineContiguousRegions = false
|
||||||
|
|
||||||
|
;# {InworldRestartShutsDown} {} {Shutdown instance on region restart?} {true false} false
|
||||||
;; If you have only one region in an instance, or to avoid the many bugs
|
;; If you have only one region in an instance, or to avoid the many bugs
|
||||||
;; that you can trigger in modules by restarting a region, set this to
|
;; that you can trigger in modules by restarting a region, set this to
|
||||||
;; true to make the entire instance exit instead of restarting the region.
|
;; true to make the entire instance exit instead of restarting the region.
|
||||||
|
@ -131,14 +136,17 @@
|
||||||
;; If both of these values are set to zero then persistence of all changed
|
;; If both of these values are set to zero then persistence of all changed
|
||||||
;; objects will happen on every sweep.
|
;; objects will happen on every sweep.
|
||||||
|
|
||||||
|
;# {MinimumTimeBeforePersistenceConsidered} {} {Time before un-changed object may be persisted} {} 60
|
||||||
;; Objects will be considered for persistance in the next sweep when they
|
;; Objects will be considered for persistance in the next sweep when they
|
||||||
;; have not changed for this number of seconds.
|
;; have not changed for this number of seconds.
|
||||||
; MinimumTimeBeforePersistenceConsidered = 60
|
; MinimumTimeBeforePersistenceConsidered = 60
|
||||||
|
|
||||||
|
;# {MaximumTimeBeforePersistenceConsidered} {} {Time before changed objects may be persisted?} {} 600
|
||||||
;; Objects will always be considered for persistance in the next sweep
|
;; Objects will always be considered for persistance in the next sweep
|
||||||
;; if the first change occurred this number of seconds ago.
|
;; if the first change occurred this number of seconds ago.
|
||||||
; MaximumTimeBeforePersistenceConsidered = 600
|
; MaximumTimeBeforePersistenceConsidered = 600
|
||||||
|
|
||||||
|
;# {see_into_this_sim_from_neighbor} {} {Should avatars in neighbor sims see objects in this sim?} {true false} true
|
||||||
;; Should avatars in neighbor sims see objects in this sim?
|
;; Should avatars in neighbor sims see objects in this sim?
|
||||||
; see_into_this_sim_from_neighbor = true
|
; see_into_this_sim_from_neighbor = true
|
||||||
|
|
||||||
|
@ -153,6 +161,7 @@
|
||||||
;; Note that only the ODE physics engine currently deals with meshed
|
;; Note that only the ODE physics engine currently deals with meshed
|
||||||
;; prims in a satisfactory way.
|
;; prims in a satisfactory way.
|
||||||
|
|
||||||
|
;# {meshing} {} {Select mesher} {Meshmerizer ZeroMesher} Meshmerizer
|
||||||
;; ZeroMesher is faster but leaves the physics engine to model the mesh
|
;; ZeroMesher is faster but leaves the physics engine to model the mesh
|
||||||
;; using the basic shapes that it supports.
|
;; using the basic shapes that it supports.
|
||||||
;; Usually this is only a box.
|
;; Usually this is only a box.
|
||||||
|
@ -161,6 +170,7 @@
|
||||||
; meshing = ZeroMesher
|
; meshing = ZeroMesher
|
||||||
|
|
||||||
;; Choose one of the physics engines below
|
;; Choose one of the physics engines below
|
||||||
|
;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} OpenDynamicsEngine
|
||||||
;; OpenDynamicsEngine is by some distance the most developed physics engine
|
;; OpenDynamicsEngine is by some distance the most developed physics engine
|
||||||
;; BulletSim is incomplete and experimental but in active development
|
;; BulletSim is incomplete and experimental but in active development
|
||||||
;; basicphysics effectively does not model physics at all, making all objects phantom
|
;; basicphysics effectively does not model physics at all, making all objects phantom
|
||||||
|
@ -184,38 +194,52 @@
|
||||||
;; If set to true, then all permissions checks are carried out
|
;; If set to true, then all permissions checks are carried out
|
||||||
; serverside_object_permissions = true
|
; serverside_object_permissions = true
|
||||||
|
|
||||||
|
;# {allow_grid_gods} {} {Allow grid gods?} {true false} false
|
||||||
;; This allows users with a UserLevel of 200 or more to assume god
|
;; This allows users with a UserLevel of 200 or more to assume god
|
||||||
;; powers in the regions in this simulator.
|
;; powers in the regions in this simulator.
|
||||||
; allow_grid_gods = false
|
; allow_grid_gods = false
|
||||||
|
|
||||||
;; This allows some control over permissions
|
;; This allows some control over permissions
|
||||||
;; please note that this still doesn't duplicate SL, and is not intended to
|
;; please note that this still doesn't duplicate SL, and is not intended to
|
||||||
|
;# {region_owner_is_god} {} {Allow region owner gods} {true false} true
|
||||||
|
;; Allow region owners to assume god powers in their regions
|
||||||
; region_owner_is_god = true
|
; region_owner_is_god = true
|
||||||
|
|
||||||
|
;# {region_manager_is_god} {} {Allow region manager gods} {true false} false
|
||||||
|
;; Allow region managers to assume god powers in regions they manage
|
||||||
; region_manager_is_god = false
|
; region_manager_is_god = false
|
||||||
|
|
||||||
|
;# {parcel_owner_is_god} {} {Allow parcel owner gods} {true false} true
|
||||||
|
;; Allow parcel owners to assume god powers in their parcels
|
||||||
; parcel_owner_is_god = true
|
; parcel_owner_is_god = true
|
||||||
|
|
||||||
|
;# {simple_build_permissions} {} {Allow building in parcel by access list (no groups)} {true false} false
|
||||||
;; More control over permissions
|
;; More control over permissions
|
||||||
;; This is definitely not SL!
|
;; This is definitely not SL!
|
||||||
; Provides a simple control for land owners to give build rights to specific avatars
|
;; Provides a simple control for land owners to give build rights to specific avatars
|
||||||
; in publicly accessible parcels that disallow object creation in general.
|
;; in publicly accessible parcels that disallow object creation in general.
|
||||||
; Owners specific avatars by adding them to the Access List of the parcel
|
;; Owners specific avatars by adding them to the Access List of the parcel
|
||||||
; without having to use the Groups feature
|
;; without having to use the Groups feature
|
||||||
; simple_build_permissions = false
|
; simple_build_permissions = false
|
||||||
|
|
||||||
|
|
||||||
|
;# {DefaultScriptEngine} {} {Default script engine} {XEngine} XEngine
|
||||||
;; Default script engine to use. Currently, we only have XEngine
|
;; Default script engine to use. Currently, we only have XEngine
|
||||||
; DefaultScriptEngine = "XEngine"
|
; DefaultScriptEngine = "XEngine"
|
||||||
|
|
||||||
|
;# {GenerateMaptiles} {} {Generate map tiles?} {true false} true
|
||||||
;; Map tile options. You can choose to generate no map tiles at all,
|
;; Map tile options. You can choose to generate no map tiles at all,
|
||||||
;; generate normal maptiles, or nominate an uploaded texture to
|
;; generate normal maptiles, or nominate an uploaded texture to
|
||||||
;; be the map tile
|
;; be the map tile
|
||||||
; GenerateMaptiles = true
|
; GenerateMaptiles = true
|
||||||
|
|
||||||
|
;# {MaptileRefresh} {GenerateMaptiles} {Maptile refresh period?} {} 0
|
||||||
;; If desired, a running region can update the map tiles periodically
|
;; If desired, a running region can update the map tiles periodically
|
||||||
;; to reflect building activity. This names no sense of you don't have
|
;; to reflect building activity. This names no sense of you don't have
|
||||||
;; prims on maptiles. Value is in seconds.
|
;; prims on maptiles. Value is in seconds.
|
||||||
; MaptileRefresh = 0
|
; MaptileRefresh = 0
|
||||||
|
|
||||||
|
;# {MaptileStaticUUID} {} {Asset ID for static map texture} {} 00000000-0000-0000-0000-000000000000
|
||||||
;; If not generating maptiles, use this static texture asset ID
|
;; If not generating maptiles, use this static texture asset ID
|
||||||
; MaptileStaticUUID = "00000000-0000-0000-0000-000000000000"
|
; MaptileStaticUUID = "00000000-0000-0000-0000-000000000000"
|
||||||
|
|
||||||
|
@ -228,9 +252,11 @@
|
||||||
;; got a large number of objects, so you can turn it off here if you'd like.
|
;; got a large number of objects, so you can turn it off here if you'd like.
|
||||||
; DrawPrimOnMapTile = true
|
; DrawPrimOnMapTile = true
|
||||||
|
|
||||||
|
;# {HttpProxy} {} {Proxy URL for llHTTPRequest and dynamic texture loading} {} http://proxy.com:8080
|
||||||
;; Http proxy setting for llHTTPRequest and dynamic texture loading, if required
|
;; Http proxy setting for llHTTPRequest and dynamic texture loading, if required
|
||||||
; HttpProxy = "http://proxy.com:8080"
|
; HttpProxy = "http://proxy.com:8080"
|
||||||
|
|
||||||
|
;# {HttpProxyExceptions} {HttpProxy} {Set of regular expressions defining URL that should not be proxied} {}
|
||||||
;; If you're using HttpProxy, then you can set HttpProxyExceptions to a list of regular expressions for URLs that you don't want to go through the proxy
|
;; If you're using HttpProxy, then you can set HttpProxyExceptions to a list of regular expressions for URLs that you don't want to go through the proxy
|
||||||
;; For example, servers inside your firewall.
|
;; For example, servers inside your firewall.
|
||||||
;; Separate patterns with a ';'
|
;; Separate patterns with a ';'
|
||||||
|
@ -254,7 +280,8 @@
|
||||||
;; default is false
|
;; default is false
|
||||||
; TelehubAllowLandmark = false
|
; TelehubAllowLandmark = false
|
||||||
|
|
||||||
;# Comma separated list of viewers which may gain access to the regions.
|
;# {AllowedViewerList} {} {Comma separated list of allowed viewers} {}
|
||||||
|
;; Comma separated list of viewers which may gain access to the regions.
|
||||||
;; One can use a Substring of the viewer name to enable only certain subversions
|
;; One can use a Substring of the viewer name to enable only certain subversions
|
||||||
;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
|
;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
|
||||||
;; - "Imprudence" has access
|
;; - "Imprudence" has access
|
||||||
|
@ -262,6 +289,7 @@
|
||||||
;; - "Imprudence 1.3.1" has no access
|
;; - "Imprudence 1.3.1" has no access
|
||||||
;; AllowedViewerList =
|
;; AllowedViewerList =
|
||||||
|
|
||||||
|
;# {BannedViewerList} {} {Comma separated list of banned viewers} {}
|
||||||
;# Comma separated list of viewers which may not gain access to the regions.
|
;# Comma separated list of viewers which may not gain access to the regions.
|
||||||
;; One can use a Substring of the viewer name to disable only certain subversions
|
;; One can use a Substring of the viewer name to disable only certain subversions
|
||||||
;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
|
;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
|
||||||
|
@ -276,16 +304,30 @@
|
||||||
; If these values are uncommented then they will be used to create a default estate as necessary.
|
; If these values are uncommented then they will be used to create a default estate as necessary.
|
||||||
; New regions will be automatically assigned to that default estate.
|
; New regions will be automatically assigned to that default estate.
|
||||||
|
|
||||||
|
;# {DefaultEstateName} {} {Default name for estate?} {} My Estate
|
||||||
|
;; Name for the default estate
|
||||||
; DefaultEstateName = My Estate
|
; DefaultEstateName = My Estate
|
||||||
|
|
||||||
|
;# {DefaultEstateOwnerName} {} {Default estate owner name?} {} FirstName LastName
|
||||||
|
;; Name for default estate owner
|
||||||
; DefaultEstateOwnerName = FirstName LastName
|
; DefaultEstateOwnerName = FirstName LastName
|
||||||
|
|
||||||
; The following parameters will only be used on a standalone system to create an estate owner that does not already exist
|
|
||||||
|
|
||||||
; If DefaultEstateOwnerUUID is left at UUID.Zero (as below) then a random UUID will be assigned.
|
; ** Standalone Estate Settings **
|
||||||
; This is normally what you want
|
; The following parameters will only be used on a standalone system to
|
||||||
|
; create an estate owner that does not already exist
|
||||||
|
|
||||||
|
;# {DefaultEstateOwnerUUID} {} {Default estate owner UUID?} {} 00000000-0000-0000-0000-000000000000
|
||||||
|
;; If DefaultEstateOwnerUUID is left at UUID.Zero (as below) then a random
|
||||||
|
;; UUID will be assigned. This is normally what you want
|
||||||
; DefaultEstateOwnerUUID = 00000000-0000-0000-0000-000000000000
|
; DefaultEstateOwnerUUID = 00000000-0000-0000-0000-000000000000
|
||||||
|
|
||||||
|
;# {DefaultEstateOwnerEMail} {} {Default estate owner email?} {}
|
||||||
|
;; Email address for the default estate owner
|
||||||
; DefaultEstateOwnerEMail = owner@domain.com
|
; DefaultEstateOwnerEMail = owner@domain.com
|
||||||
|
|
||||||
|
;# {DefaultEstateOwnerPassword} {} {Default estate owner password} {}
|
||||||
|
;; Password for the default estate owner
|
||||||
; DefaultEstateOwnerPassword = password
|
; DefaultEstateOwnerPassword = password
|
||||||
|
|
||||||
|
|
||||||
|
@ -322,10 +364,14 @@
|
||||||
; SMTP_SERVER_PASSWORD = ""
|
; SMTP_SERVER_PASSWORD = ""
|
||||||
|
|
||||||
[Network]
|
[Network]
|
||||||
|
|
||||||
|
;# {ConsoleUser} {} {User name for console account} {}
|
||||||
;; Configure the remote console user here. This will not actually be used
|
;; Configure the remote console user here. This will not actually be used
|
||||||
;; unless you use -console=rest at startup.
|
;; unless you use -console=rest at startup.
|
||||||
; ConsoleUser = "Test"
|
; ConsoleUser = "Test"
|
||||||
|
;# {ConsolePass} {} {Password for console account} {}
|
||||||
; ConsolePass = "secret"
|
; ConsolePass = "secret"
|
||||||
|
;# {console_port} {} {Port for console connections} {} 0
|
||||||
; console_port = 0
|
; console_port = 0
|
||||||
|
|
||||||
;# {http_listener_port} {} {TCP Port for this simulator to listen on? (This must be unique to the simulator!)} {} 9000
|
;# {http_listener_port} {} {TCP Port for this simulator to listen on? (This must be unique to the simulator!)} {} 9000
|
||||||
|
@ -389,11 +435,14 @@
|
||||||
|
|
||||||
|
|
||||||
[SimulatorFeatures]
|
[SimulatorFeatures]
|
||||||
|
|
||||||
|
;# {MapImageServerURI} {} {URL for the map server} {}
|
||||||
; Experimental new information sent in SimulatorFeatures cap for Kokua viewers
|
; Experimental new information sent in SimulatorFeatures cap for Kokua viewers
|
||||||
; meant to override the MapImage and search server url given at login, and varying
|
; meant to override the MapImage and search server url given at login, and varying
|
||||||
; on a sim-basis.
|
; on a sim-basis.
|
||||||
; Viewers that don't understand it, will ignore it
|
; Viewers that don't understand it, will ignore it
|
||||||
;MapImageServerURI = "http://127.0.0.1:9000/"
|
;MapImageServerURI = "http://127.0.0.1:9000/"
|
||||||
|
;# {SearchServerURI} {} {URL of the search server} {}
|
||||||
;SearchServerURI = "http://127.0.0.1:9000/"
|
;SearchServerURI = "http://127.0.0.1:9000/"
|
||||||
|
|
||||||
|
|
||||||
|
@ -587,6 +636,7 @@
|
||||||
|
|
||||||
|
|
||||||
[Economy]
|
[Economy]
|
||||||
|
;# {SellEnabled} {} {Enable selling for 0?} {true false} true
|
||||||
; The default economy module only implements just enough to allow free actions (transfer of objects, etc).
|
; The default economy module only implements just enough to allow free actions (transfer of objects, etc).
|
||||||
; There is no intention to implement anything further in core OpenSimulator.
|
; There is no intention to implement anything further in core OpenSimulator.
|
||||||
; This functionality has to be provided by third party modules.
|
; This functionality has to be provided by third party modules.
|
||||||
|
@ -594,9 +644,11 @@
|
||||||
;; Enables selling things for $0. Default is true.
|
;; Enables selling things for $0. Default is true.
|
||||||
; SellEnabled = true
|
; SellEnabled = true
|
||||||
|
|
||||||
|
;# {PriceUpload} {} {Price for uploading?} {} 0
|
||||||
;; Money Unit fee to upload textures, animations etc. Default is 0.
|
;; Money Unit fee to upload textures, animations etc. Default is 0.
|
||||||
; PriceUpload = 0
|
; PriceUpload = 0
|
||||||
|
|
||||||
|
;# {PriceGroupCreate} {} {Fee for group creation} {} 0
|
||||||
;; Money Unit fee to create groups. Default is 0.
|
;; Money Unit fee to create groups. Default is 0.
|
||||||
; PriceGroupCreate = 0
|
; PriceGroupCreate = 0
|
||||||
|
|
||||||
|
@ -706,32 +758,41 @@
|
||||||
; If both Allow_ and Creators_ are given, effective permissions
|
; If both Allow_ and Creators_ are given, effective permissions
|
||||||
; are the union of the two.
|
; are the union of the two.
|
||||||
|
|
||||||
|
;# {EventLimit} {} {Amount of time a script can spend in an event handler} {} 30
|
||||||
;; Time a script can spend in an event handler before it is interrupted
|
;; Time a script can spend in an event handler before it is interrupted
|
||||||
; EventLimit = 30
|
; EventLimit = 30
|
||||||
|
|
||||||
|
;# {KillTimedOutScripts} {} {Kill script in case of event time overruns?} {true false} false
|
||||||
;; If a script overruns it's event limit, kill the script?
|
;; If a script overruns it's event limit, kill the script?
|
||||||
; KillTimedOutScripts = false
|
; KillTimedOutScripts = false
|
||||||
|
|
||||||
|
;# {ScriptDelayFactor} {} {Multiplier for scripting delays} {} 1.0
|
||||||
;; Sets the multiplier for the scripting delays
|
;; Sets the multiplier for the scripting delays
|
||||||
; ScriptDelayFactor = 1.0
|
; ScriptDelayFactor = 1.0
|
||||||
|
|
||||||
|
;# {ScriptDistanceLimitFactor} {} {Multiplier for 10.0m distance limits?} {}
|
||||||
;; The factor the 10 m distances limits are multiplied by
|
;; The factor the 10 m distances limits are multiplied by
|
||||||
; ScriptDistanceLimitFactor = 1.0
|
; ScriptDistanceLimitFactor = 1.0
|
||||||
|
|
||||||
|
;# {NotecardLineReadCharsMax} {} {Maximum length of notecard line?} {} 255
|
||||||
;; Maximum length of notecard line read
|
;; Maximum length of notecard line read
|
||||||
;; Increasing this to large values potentially opens
|
;; Increasing this to large values potentially opens
|
||||||
;; up the system to malicious scripters
|
;; up the system to malicious scripters
|
||||||
; NotecardLineReadCharsMax = 255
|
; NotecardLineReadCharsMax = 255
|
||||||
|
|
||||||
|
;# {SensorMaxRange} {} {Sensor range} {} 96.0
|
||||||
;; Sensor settings
|
;; Sensor settings
|
||||||
; SensorMaxRange = 96.0
|
; SensorMaxRange = 96.0
|
||||||
|
;# {SensorMaxResults} {} {Max sensor results returned?} {}
|
||||||
; SensorMaxResults = 16
|
; SensorMaxResults = 16
|
||||||
|
|
||||||
|
;# {DisableUndergroundMovement} {} {Disable underground movement of prims} {true false} true
|
||||||
;; Disable underground movement of prims (default true); set to
|
;; Disable underground movement of prims (default true); set to
|
||||||
;; false to allow script controlled underground positioning of
|
;; false to allow script controlled underground positioning of
|
||||||
;; prims
|
;; prims
|
||||||
; DisableUndergroundMovement = true
|
; DisableUndergroundMovement = true
|
||||||
|
|
||||||
|
;# {ScriptEnginesPath} {} {Path to script assemblies} {} ScriptEngines
|
||||||
;; Path to script engine assemblies
|
;; Path to script engine assemblies
|
||||||
;; Default is ./bin/ScriptEngines
|
;; Default is ./bin/ScriptEngines
|
||||||
; ScriptEnginesPath = "ScriptEngines"
|
; ScriptEnginesPath = "ScriptEngines"
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3138,6 +3138,7 @@
|
||||||
|
|
||||||
<ReferencePath>../../../bin/</ReferencePath>
|
<ReferencePath>../../../bin/</ReferencePath>
|
||||||
<Reference name="System"/>
|
<Reference name="System"/>
|
||||||
|
<Reference name="System.Core"/>
|
||||||
<Reference name="System.Xml"/>
|
<Reference name="System.Xml"/>
|
||||||
<Reference name="System.Drawing"/>
|
<Reference name="System.Drawing"/>
|
||||||
<Reference name="System.Runtime.Remoting"/>
|
<Reference name="System.Runtime.Remoting"/>
|
||||||
|
|
Loading…
Reference in New Issue