merge crap gerge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork

Conflicts:
	bin/Regions/Regions.ini.example
	bin/lib32/BulletSim.dll
	bin/lib32/libBulletSim.so
	bin/lib64/BulletSim.dll
	bin/lib64/libBulletSim.so
avinationmerge
ubit 2012-08-02 18:21:08 +02:00
commit 254d3e1ad3
101 changed files with 3570 additions and 1367 deletions

2
.gitignore vendored
View File

@ -44,6 +44,8 @@ bin/Physics*
bin/Terrain*
bin/Regions/*
bin/UserAssets
bin/assetcache
bin/maptiles
bin/estate_settings.xml
bin/config-include/CenomeCache.ini
bin/config-include/FlotsamCache.ini

View File

@ -66,6 +66,19 @@ namespace OpenSim.Framework
IConfigSource Config { get; }
/// <summary>
/// Are logins enabled on this simulator?
/// </summary>
bool LoginsEnabled { get; set; }
/// <summary>
/// Is this region ready for use?
/// </summary>
/// <remarks>
/// This does not mean that logins are enabled, merely that they can be.
/// </remarks>
bool Ready { get; set; }
float TimeDilation { get; }
bool AllowScriptCrossings { get; }

View File

@ -28,7 +28,7 @@
using System;
using System.Timers;
namespace OpenSim.Framework.Statistics
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Asset service statistics collection

View File

@ -31,8 +31,7 @@ using System.Text;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework.Statistics
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Statistics which all collectors are interested in reporting

View File

@ -25,7 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace OpenSim.Framework.Statistics.Interfaces
namespace OpenSim.Framework.Monitoring.Interfaces
{
/// <summary>
/// Implemented by objects which allow statistical information to be pulled from them.

View File

@ -25,7 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace OpenSim.Framework.Statistics
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Implemented by classes which collect up non-viewer statistical information

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using log4net;
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Experimental watchdog for memory usage.
/// </summary>
public static class MemoryWatchdog
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Is this watchdog active?
/// </summary>
public static bool Enabled
{
get { return m_enabled; }
set
{
// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value);
if (value && !m_enabled)
UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount());
m_enabled = value;
}
}
private static bool m_enabled;
/// <summary>
/// Average memory churn in bytes per millisecond.
/// </summary>
public static double AverageMemoryChurn
{
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
}
/// <summary>
/// Maximum number of statistical samples.
/// </summary>
/// <remarks>
/// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from
/// the main Watchdog.
/// </remarks>
private static int m_maxSamples = 24;
/// <summary>
/// Time when the watchdog was last updated.
/// </summary>
private static int m_lastUpdateTick;
/// <summary>
/// Memory used at time of last watchdog update.
/// </summary>
private static long m_lastUpdateMemory;
/// <summary>
/// Memory churn rate per millisecond.
/// </summary>
// private static double m_churnRatePerMillisecond;
/// <summary>
/// Historical samples for calculating moving average.
/// </summary>
private static Queue<double> m_samples = new Queue<double>(m_maxSamples);
public static void Update()
{
int now = Util.EnvironmentTickCount();
long memoryNow = GC.GetTotalMemory(false);
long memoryDiff = memoryNow - m_lastUpdateMemory;
if (memoryDiff >= 0)
{
if (m_samples.Count >= m_maxSamples)
m_samples.Dequeue();
double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick);
// This should never happen since it's not useful for updates to occur with no time elapsed, but
// protect ourselves from a divide-by-zero just in case.
if (elapsed == 0)
return;
m_samples.Enqueue(memoryDiff / (double)elapsed);
}
UpdateLastRecord(memoryNow, now);
}
private static void UpdateLastRecord(long memoryNow, int timeNow)
{
m_lastUpdateMemory = memoryNow;
m_lastUpdateTick = timeNow;
}
}
}

View File

@ -28,12 +28,11 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenMetaverse;
using OpenSim.Framework.Statistics.Interfaces;
using OpenMetaverse.StructuredData;
using OpenSim.Framework.Monitoring.Interfaces;
namespace OpenSim.Framework.Statistics
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane

View File

@ -25,7 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace OpenSim.Framework.Statistics
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Singleton used to provide access to statistics reporters

View File

@ -27,7 +27,7 @@
using System.Timers;
namespace OpenSim.Framework.Statistics
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Collects user service statistics

View File

@ -31,7 +31,7 @@ using System.Linq;
using System.Threading;
using log4net;
namespace OpenSim.Framework
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Manages launching threads and keeping watch over them for timeouts
@ -325,6 +325,9 @@ namespace OpenSim.Framework
callback(callbackInfo);
}
if (MemoryWatchdog.Enabled)
MemoryWatchdog.Update();
m_watchdogTimer.Start();
}
}

View File

@ -482,9 +482,16 @@ namespace OpenSim.Framework
MainConsole.Instance.Output("=====================================\n");
if (name == String.Empty)
name = MainConsole.Instance.CmdPrompt("New region name", name);
if (name == String.Empty)
throw new Exception("Cannot interactively create region with no name");
{
while (name.Trim() == string.Empty)
{
name = MainConsole.Instance.CmdPrompt("New region name", name);
if (name.Trim() == string.Empty)
{
MainConsole.Instance.Output("Cannot interactively create region with no name");
}
}
}
source.AddConfig(name);
@ -515,15 +522,20 @@ namespace OpenSim.Framework
//
allKeys.Remove("RegionUUID");
string regionUUID = config.GetString("RegionUUID", string.Empty);
if (regionUUID == String.Empty)
if (!UUID.TryParse(regionUUID.Trim(), out RegionID))
{
UUID newID = UUID.Random();
regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString());
while (RegionID == UUID.Zero)
{
regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString());
if (!UUID.TryParse(regionUUID.Trim(), out RegionID))
{
MainConsole.Instance.Output("RegionUUID must be a valid UUID");
}
}
config.Set("RegionUUID", regionUUID);
}
RegionID = new UUID(regionUUID);
originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?)
// Location

View File

@ -40,9 +40,9 @@ using log4net.Core;
using log4net.Repository;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Framework.Statistics;
using Timer=System.Timers.Timer;
using OpenMetaverse;

View File

@ -45,6 +45,7 @@ using OpenMetaverse.StructuredData;
using CoolHTTPListener = HttpServer.HttpListener;
using HttpListener=System.Net.HttpListener;
using LogPrio=HttpServer.LogPrio;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Framework.Servers.HttpServer
{

View File

@ -32,6 +32,7 @@ using System.Reflection;
using log4net;
using HttpServer;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
/*

View File

@ -36,6 +36,7 @@ using HttpServer;
using OpenMetaverse;
using System.Reflection;
using log4net;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Framework.Servers.HttpServer
{

View File

@ -40,7 +40,7 @@ using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
@ -200,9 +200,9 @@ namespace OpenSim
PrintFileToConsole("startuplogo.txt");
// For now, start at the 'root' level by default
if (m_sceneManager.Scenes.Count == 1) // If there is only one region, select it
if (SceneManager.Scenes.Count == 1) // If there is only one region, select it
ChangeSelectedRegion("region",
new string[] {"change", "region", m_sceneManager.Scenes[0].RegionInfo.RegionName});
new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName});
else
ChangeSelectedRegion("region", new string[] {"change", "region", "root"});
@ -461,7 +461,7 @@ namespace OpenSim
if (cmdparams.Length > 4)
alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
IList agents = m_sceneManager.GetCurrentSceneAvatars();
IList agents = SceneManager.GetCurrentSceneAvatars();
foreach (ScenePresence presence in agents)
{
@ -542,7 +542,7 @@ namespace OpenSim
private void HandleForceUpdate(string module, string[] args)
{
MainConsole.Instance.Output("Updating all clients");
m_sceneManager.ForceCurrentSceneClientUpdate();
SceneManager.ForceCurrentSceneClientUpdate();
}
/// <summary>
@ -554,7 +554,7 @@ namespace OpenSim
{
if (args.Length == 6)
{
m_sceneManager.HandleEditCommandOnCurrentScene(args);
SceneManager.HandleEditCommandOnCurrentScene(args);
}
else
{
@ -765,7 +765,7 @@ namespace OpenSim
case "load":
if (cmdparams.Length > 1)
{
foreach (Scene s in new ArrayList(m_sceneManager.Scenes))
foreach (Scene s in new ArrayList(SceneManager.Scenes))
{
MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1]));
m_moduleLoader.LoadRegionModules(cmdparams[1], s);
@ -803,14 +803,14 @@ namespace OpenSim
case "backup":
MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
m_sceneManager.BackupCurrentScene();
SceneManager.BackupCurrentScene();
break;
case "remove-region":
string regRemoveName = CombineParams(cmdparams, 0);
Scene removeScene;
if (m_sceneManager.TryGetScene(regRemoveName, out removeScene))
if (SceneManager.TryGetScene(regRemoveName, out removeScene))
RemoveRegion(removeScene, false);
else
MainConsole.Instance.Output("No region with that name");
@ -820,14 +820,14 @@ namespace OpenSim
string regDeleteName = CombineParams(cmdparams, 0);
Scene killScene;
if (m_sceneManager.TryGetScene(regDeleteName, out killScene))
if (SceneManager.TryGetScene(regDeleteName, out killScene))
RemoveRegion(killScene, true);
else
MainConsole.Instance.Output("no region with that name");
break;
case "restart":
m_sceneManager.RestartCurrentScene();
SceneManager.RestartCurrentScene();
break;
}
}
@ -842,7 +842,7 @@ namespace OpenSim
{
string newRegionName = CombineParams(cmdparams, 2);
if (!m_sceneManager.TrySetCurrentScene(newRegionName))
if (!SceneManager.TrySetCurrentScene(newRegionName))
MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
}
else
@ -850,7 +850,7 @@ namespace OpenSim
MainConsole.Instance.Output("Usage: change region <region name>");
}
string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName);
string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
// m_log.DebugFormat("Original prompt is {0}", m_consolePrompt);
@ -868,7 +868,7 @@ namespace OpenSim
});
m_console.DefaultPrompt = prompt;
m_console.ConsoleScene = m_sceneManager.CurrentScene;
m_console.ConsoleScene = SceneManager.CurrentScene;
}
/// <summary>
@ -892,7 +892,7 @@ namespace OpenSim
int newDebug;
if (int.TryParse(args[2], out newDebug))
{
m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
// We provide user information elsewhere if any clients had their debug level set.
// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
}
@ -907,7 +907,7 @@ namespace OpenSim
case "scene":
if (args.Length == 4)
{
if (m_sceneManager.CurrentScene == null)
if (SceneManager.CurrentScene == null)
{
MainConsole.Instance.Output("Please use 'change region <regioname>' first");
}
@ -915,7 +915,7 @@ namespace OpenSim
{
string key = args[2];
string value = args[3];
m_sceneManager.CurrentScene.SetSceneCoreDebug(
SceneManager.CurrentScene.SetSceneCoreDebug(
new Dictionary<string, string>() { { key, value } });
MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value);
@ -954,10 +954,10 @@ namespace OpenSim
IList agents;
if (showParams.Length > 1 && showParams[1] == "full")
{
agents = m_sceneManager.GetCurrentScenePresences();
agents = SceneManager.GetCurrentScenePresences();
} else
{
agents = m_sceneManager.GetCurrentSceneAvatars();
agents = SceneManager.GetCurrentSceneAvatars();
}
MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count));
@ -1037,7 +1037,7 @@ namespace OpenSim
MainConsole.Instance.Output("Shared Module: " + module.Name);
}
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
delegate(Scene scene) {
m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModule module in scene.Modules.Values)
@ -1050,7 +1050,7 @@ namespace OpenSim
}
);
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
delegate(Scene scene) {
MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:");
foreach (IRegionModuleBase module in scene.RegionModules.Values)
@ -1066,7 +1066,7 @@ namespace OpenSim
break;
case "regions":
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
delegate(Scene scene)
{
MainConsole.Instance.Output(String.Format(
@ -1080,7 +1080,7 @@ namespace OpenSim
break;
case "ratings":
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
delegate(Scene scene)
{
string rating = "";
@ -1115,7 +1115,7 @@ namespace OpenSim
cdt.AddColumn("IP", 16);
cdt.AddColumn("Viewer Name", 24);
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
s =>
{
foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
@ -1140,13 +1140,13 @@ namespace OpenSim
cdt.AddColumn("Endpoint", 23);
cdt.AddColumn("Active?", 7);
m_sceneManager.ForEachScene(
SceneManager.ForEachScene(
s => s.ForEachClient(
c => cdt.AddRow(
s.Name,
c.Name,
c.RemoteEndPoint.ToString(),
c.CircuitCode.ToString(),
c.RemoteEndPoint.ToString(),
c.IsActive.ToString())));
MainConsole.Instance.Output(cdt.ToString());
@ -1161,11 +1161,11 @@ namespace OpenSim
{
if (cmdparams.Length > 5)
{
m_sceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
}
else
{
m_sceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
}
}
@ -1180,11 +1180,11 @@ namespace OpenSim
if (cmdparams.Length > 0)
{
m_sceneManager.SaveCurrentSceneToXml(cmdparams[2]);
SceneManager.SaveCurrentSceneToXml(cmdparams[2]);
}
else
{
m_sceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
}
}
@ -1221,13 +1221,13 @@ namespace OpenSim
MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
}
}
m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset);
SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset);
}
else
{
try
{
m_sceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
}
catch (FileNotFoundException)
{
@ -1244,11 +1244,11 @@ namespace OpenSim
{
if (cmdparams.Length > 2)
{
m_sceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
SceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
}
else
{
m_sceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
}
}
@ -1263,7 +1263,7 @@ namespace OpenSim
{
try
{
m_sceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
}
catch (FileNotFoundException)
{
@ -1274,7 +1274,7 @@ namespace OpenSim
{
try
{
m_sceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
}
catch (FileNotFoundException)
{
@ -1291,7 +1291,7 @@ namespace OpenSim
{
try
{
m_sceneManager.LoadArchiveToCurrentScene(cmdparams);
SceneManager.LoadArchiveToCurrentScene(cmdparams);
}
catch (Exception e)
{
@ -1305,7 +1305,7 @@ namespace OpenSim
/// <param name="cmdparams"></param>
protected void SaveOar(string module, string[] cmdparams)
{
m_sceneManager.SaveCurrentSceneToArchive(cmdparams);
SceneManager.SaveCurrentSceneToArchive(cmdparams);
}
private static string CombineParams(string[] commandParams, int pos)

View File

@ -40,7 +40,7 @@ using OpenSim.Framework.Communications;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.ClientStack;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts;
using OpenSim.Region.Framework;
@ -300,7 +300,7 @@ namespace OpenSim
private void HandleCommanderCommand(string module, string[] cmd)
{
m_sceneManager.SendCommandToPluginModules(cmd);
SceneManager.SendCommandToPluginModules(cmd);
}
private void HandleCommanderHelp(string module, string[] cmd)
@ -318,7 +318,10 @@ namespace OpenSim
// Called from base.StartUp()
m_httpServerPort = m_networkServersInfo.HttpListenerPort;
m_sceneManager.OnRestartSim += handleRestartRegion;
SceneManager.OnRestartSim += handleRestartRegion;
// Only start the memory watchdog once all regions are ready
SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady;
}
/// <summary>
@ -480,7 +483,7 @@ namespace OpenSim
scene.SnmpService.BootInfo("ScriptEngine started", scene);
}
m_sceneManager.Add(scene);
SceneManager.Add(scene);
if (m_autoCreateClientStack)
{
@ -510,7 +513,6 @@ namespace OpenSim
}
scene.Start();
scene.StartScripts();
return clientServer;
@ -644,14 +646,14 @@ namespace OpenSim
{
// only need to check this if we are not at the
// root level
if ((m_sceneManager.CurrentScene != null) &&
(m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
if ((SceneManager.CurrentScene != null) &&
(SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
{
m_sceneManager.TrySetCurrentScene("..");
SceneManager.TrySetCurrentScene("..");
}
scene.DeleteAllSceneObjects();
m_sceneManager.CloseScene(scene);
SceneManager.CloseScene(scene);
ShutdownClientServer(scene.RegionInfo);
if (!cleanup)
@ -693,7 +695,7 @@ namespace OpenSim
public void RemoveRegion(string name, bool cleanUp)
{
Scene target;
if (m_sceneManager.TryGetScene(name, out target))
if (SceneManager.TryGetScene(name, out target))
RemoveRegion(target, cleanUp);
}
@ -706,13 +708,13 @@ namespace OpenSim
{
// only need to check this if we are not at the
// root level
if ((m_sceneManager.CurrentScene != null) &&
(m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
if ((SceneManager.CurrentScene != null) &&
(SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
{
m_sceneManager.TrySetCurrentScene("..");
SceneManager.TrySetCurrentScene("..");
}
m_sceneManager.CloseScene(scene);
SceneManager.CloseScene(scene);
ShutdownClientServer(scene.RegionInfo);
}
@ -724,7 +726,7 @@ namespace OpenSim
public void CloseRegion(string name)
{
Scene target;
if (m_sceneManager.TryGetScene(name, out target))
if (SceneManager.TryGetScene(name, out target))
CloseRegion(target);
}
@ -781,6 +783,7 @@ namespace OpenSim
scene.LoadWorldMap();
scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName);
scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset;
scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight);
@ -980,7 +983,7 @@ namespace OpenSim
try
{
m_sceneManager.Close();
SceneManager.Close();
}
catch (Exception e)
{
@ -1005,7 +1008,7 @@ namespace OpenSim
/// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param>
public void GetAvatarNumber(out int usernum)
{
usernum = m_sceneManager.GetCurrentSceneAvatars().Count;
usernum = SceneManager.GetCurrentSceneAvatars().Count;
}
/// <summary>
@ -1014,7 +1017,7 @@ namespace OpenSim
/// <param name="regionnum">The first out parameter describing the number of regions</param>
public void GetRegionNumber(out int regionnum)
{
regionnum = m_sceneManager.Scenes.Count;
regionnum = SceneManager.Scenes.Count;
}
/// <summary>

View File

@ -41,7 +41,7 @@ using OpenMetaverse.Messages.Linden;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
@ -355,8 +355,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private int m_animationSequenceNumber = 1;
private bool m_SendLogoutPacketWhenClosing = true;
private AgentUpdateArgs lastarg;
private bool m_IsActive = true;
private bool m_IsLoggingOut = false;
protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@ -428,16 +426,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public uint CircuitCode { get { return m_circuitCode; } }
public int MoneyBalance { get { return m_moneyBalance; } }
public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
public bool IsActive
{
get { return m_IsActive; }
set { m_IsActive = value; }
}
public bool IsLoggingOut
{
get { return m_IsLoggingOut; }
set { m_IsLoggingOut = value; }
}
/// <summary>
/// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
/// prevent race conditions by different threads calling Close().
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// Used to synchronise threads when client is being closed.
/// </summary>
public Object CloseSyncLock { get; private set; }
public bool IsLoggingOut { get; set; }
public bool DisableFacelights
{
@ -462,6 +463,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// DebugPacketLevel = 1;
CloseSyncLock = new Object();
RegisterInterface<IClientIM>(this);
RegisterInterface<IClientInventory>(this);
RegisterInterface<IClientChat>(this);
@ -494,13 +497,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_prioritizer = new Prioritizer(m_scene);
RegisterLocalPacketHandlers();
IsActive = true;
}
#region Client Methods
/// <summary>
/// Shut down the client view
/// Close down the client view
/// </summary>
public void Close()
{
@ -513,7 +518,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void Close(bool sendStop)
{
IsActive = false;
// We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
// a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
lock (CloseSyncLock)
{
if (!IsActive)
return;
IsActive = false;
CloseWithoutChecks(sendStop);
}
}
/// <summary>
/// Closes down the client view without first checking whether it is active.
/// </summary>
/// <remarks>
/// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling
/// CloseWithoutIsActiveCheck asynchronously.
///
/// Callers must lock ClosingSyncLock before calling.
/// </remarks>
public void CloseWithoutChecks(bool sendStop)
{
m_log.DebugFormat(
"[CLIENT]: Close has been called for {0} attached to scene {1}",
Name, m_scene.RegionInfo.RegionName);
@ -3634,7 +3661,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
{
if (!IsActive) return; // We don't need to update inactive clients.
// We don't need to update inactive clients.
if (!IsActive)
return;
CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
loc.Header.Reliable = false;
@ -5267,7 +5296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate);
AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false);
AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage);
AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship);
AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship);

View File

@ -279,7 +279,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public string GetStats()
{
return string.Format(
"{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}",
"{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}",
Util.EnvironmentTickCountSubtract(TickLastPacketReceived),
PacketsReceived,
PacketsSent,
PacketsResent,

View File

@ -37,7 +37,7 @@ using log4net;
using Nini.Config;
using OpenMetaverse.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
@ -1181,22 +1181,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// regular client pings.
/// </remarks>
/// <param name='client'></param>
private void DeactivateClientDueToTimeout(IClientAPI client)
private void DeactivateClientDueToTimeout(LLClientView client)
{
// We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
// though it's set later on by LLClientView.Close()
client.IsActive = false;
m_log.WarnFormat(
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
if (!client.SceneAgent.IsChildAgent)
client.Kick("Simulator logged you out due to connection timeout");
Util.FireAndForget(o => client.Close());
lock (client.CloseSyncLock)
{
m_log.WarnFormat(
"[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
if (!client.SceneAgent.IsChildAgent)
client.Kick("Simulator logged you out due to connection timeout");
client.CloseWithoutChecks(true);
}
}
private void IncomingPacketHandler()

View File

@ -53,9 +53,8 @@ namespace OpenSim.Region.ClientStack
protected ISimulationDataService m_simulationDataService;
protected IEstateDataService m_estateDataService;
protected ClientStackManager m_clientStackManager;
protected SceneManager m_sceneManager = new SceneManager();
public SceneManager SceneManager { get { return m_sceneManager; } }
public SceneManager SceneManager { get; protected set; }
public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } }
public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } }
public IEstateDataService EstateDataService { get { return m_estateDataService; } }
@ -77,6 +76,7 @@ namespace OpenSim.Region.ClientStack
protected override void StartupSpecific()
{
SceneManager = new SceneManager();
m_clientStackManager = CreateClientStackManager();
Initialize();

View File

@ -626,10 +626,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
m_scene.InventoryService.UpdateItem(item);
// this gets called when the agent logs off!
// If the name of the object has been changed whilst attached then we want to update the inventory
// item in the viewer.
if (sp.ControllingClient != null)
sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
}
grp.HasGroupChanged = false; // Prevent it being saved over and over
}
// else

View File

@ -47,6 +47,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
using OpenSim.Region.CoreModules.World.Serialiser;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.XEngine;
using OpenSim.Services.Interfaces;
using OpenSim.Tests.Common;
@ -289,21 +290,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
{
TestHelpers.InMethod();
Scene scene = CreateTestScene();
Scene scene = CreateScriptingEnabledTestScene();
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
TaskInventoryHelpers.AddScript(scene, so.RootPart);
TaskInventoryItem scriptItem
= TaskInventoryHelpers.AddScript(
scene,
so.RootPart,
"scriptItem",
"default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }");
InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
// FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
// In the future, we need to be able to do this programatically more predicably.
scene.EventManager.OnChatFromWorld += OnChatFromWorld;
scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
m_chatEvent.WaitOne(60000);
// TODO: Need to have a test that checks the script is actually started but this involves a lot more
// plumbing of the script engine and either pausing for events or more infrastructure to turn off various
// script engine delays/asychronicity that isn't helpful in an automated regression testing context.
SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name);
Assert.That(attSo.ContainsScripts(), Is.True);
TaskInventoryItem reRezzedScriptItem = attSo.RootPart.Inventory.GetInventoryItem(scriptItem.Name);
IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>();
Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True);
}
[Test]
@ -379,29 +396,49 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
TaskInventoryHelpers.AddScript(scene, so.RootPart);
TaskInventoryItem scriptTaskItem
= TaskInventoryHelpers.AddScript(
scene,
so.RootPart,
"scriptItem",
"default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }");
InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
// FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
// In the future, we need to be able to do this programatically more predicably.
scene.EventManager.OnChatFromWorld += OnChatFromWorld;
SceneObjectGroup soRezzed
= (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
SceneObjectGroup rezzedSo
= (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
// Wait for chat to signal rezzed script has been started.
m_chatEvent.WaitOne(60000);
scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed);
scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo);
InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem);
AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
// TODO: It would probably be better here to check script state via the saving and retrieval of state
// information at a higher level, rather than having to inspect the serialization.
XmlDocument soXml = new XmlDocument();
soXml.LoadXml(Encoding.UTF8.GetString(asset.Data));
XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState");
Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
// Re-rez the attachment to check script running state
SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
// Wait for chat to signal rezzed script has been started.
m_chatEvent.WaitOne(60000);
TaskInventoryItem reRezzedScriptItem = reRezzedSo.RootPart.Inventory.GetInventoryItem(scriptTaskItem.Name);
IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>();
Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True);
// Console.WriteLine(soXml.OuterXml);
}
/// <summary>

View File

@ -37,7 +37,7 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
scene.EventManager.OnNewClient += OnNewClient;
scene.EventManager.OnClientClosed += OnClientClosed;
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
// scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
}
public void PostInitialise()
@ -133,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
private void OnNewClient(IClientAPI client)
{
// Subscribe to instant messages
client.OnInstantMessage += OnInstantMessage;
// client.OnInstantMessage += OnInstantMessage;
client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
lock (m_ClientMap)
@ -171,15 +171,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
ActiveGroupTitle);
}
private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
{
}
// private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
// {
// }
private void OnGridInstantMessage(GridInstantMessage msg)
{
// Trigger the above event handler
OnInstantMessage(null, msg);
}
// private void OnGridInstantMessage(GridInstantMessage msg)
// {
// // Trigger the above event handler
// OnInstantMessage(null, msg);
// }
private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client)
{

View File

@ -141,13 +141,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
foreach (Scene scene in m_Scenes)
{
// m_log.DebugFormat(
// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
// toAgentID.ToString(), scene.RegionInfo.RegionName);
ScenePresence sp = scene.GetScenePresence(toAgentID);
if (sp != null && !sp.IsChildAgent)
{
// Local message
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
sp.ControllingClient.SendInstantMessage(im);
// Message sent
@ -159,13 +161,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
// try child avatar second
foreach (Scene scene in m_Scenes)
{
// m_log.DebugFormat(
// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
m_log.DebugFormat(
"[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
ScenePresence sp = scene.GetScenePresence(toAgentID);
if (sp != null)
{
// Local message
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
sp.ControllingClient.SendInstantMessage(im);
// Message sent
@ -174,10 +178,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
}
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
SendGridInstantMessageViaXMLRPC(im, result);
m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
return;
SendGridInstantMessageViaXMLRPC(im, result);
}
private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)

View File

@ -313,8 +313,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
}
}
else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)
else if (
im.dialog == (byte)InstantMessageDialog.InventoryDeclined
|| im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
{
// Here, the recipient is local and we can assume that the
// inventory is loaded. Courtesy of the above bulk update,

View File

@ -204,8 +204,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
m_Scene.AssetService.Store(asset);
m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
m_Scene.CreateNewInventoryItem(
remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
}
else
{

View File

@ -39,7 +39,7 @@ using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.Avatar.Attachments
namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")]
public class BinaryLoggingModule : INonSharedRegionModule

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Text;
using log4net;
namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
{
/// <summary>
/// Class for writing a high performance, high volume log file.
/// Sometimes, to debug, one has a high volume logging to do and the regular
/// log file output is not appropriate.
/// Create a new instance with the parameters needed and
/// call Write() to output a line. Call Close() when finished.
/// If created with no parameters, it will not log anything.
/// </summary>
public class LogWriter : IDisposable
{
public bool Enabled { get; private set; }
private string m_logDirectory = ".";
private int m_logMaxFileTimeMin = 5; // 5 minutes
public String LogFileHeader { get; set; }
private StreamWriter m_logFile = null;
private TimeSpan m_logFileLife;
private DateTime m_logFileEndTime;
private Object m_logFileWriteLock = new Object();
// set externally when debugging. If let 'null', this does not write any error messages.
public ILog ErrorLogger = null;
private string LogHeader = "[LOG WRITER]";
/// <summary>
/// Create a log writer that will not write anything. Good for when not enabled
/// but the write statements are still in the code.
/// </summary>
public LogWriter()
{
Enabled = false;
m_logFile = null;
}
/// <summary>
/// Create a log writer instance.
/// </summary>
/// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
/// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
/// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
public LogWriter(string dir, string headr, int maxFileTime)
{
m_logDirectory = dir == null ? "." : dir;
LogFileHeader = headr == null ? "log-" : headr;
m_logMaxFileTimeMin = maxFileTime;
if (m_logMaxFileTimeMin < 1)
m_logMaxFileTimeMin = 5;
m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
m_logFileEndTime = DateTime.Now + m_logFileLife;
Enabled = true;
}
public void Dispose()
{
this.Close();
}
public void Close()
{
Enabled = false;
if (m_logFile != null)
{
m_logFile.Close();
m_logFile.Dispose();
m_logFile = null;
}
}
public void Write(string line, params object[] args)
{
if (!Enabled) return;
Write(String.Format(line, args));
}
public void Write(string line)
{
if (!Enabled) return;
try
{
lock (m_logFileWriteLock)
{
DateTime now = DateTime.Now;
if (m_logFile == null || now > m_logFileEndTime)
{
if (m_logFile != null)
{
m_logFile.Close();
m_logFile.Dispose();
m_logFile = null;
}
// First log file or time has expired, start writing to a new log file
m_logFileEndTime = now + m_logFileLife;
string path = (m_logDirectory.Length > 0 ? m_logDirectory
+ System.IO.Path.DirectorySeparatorChar.ToString() : "")
+ String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
}
if (m_logFile != null)
{
StringBuilder buff = new StringBuilder(line.Length + 25);
buff.Append(now.ToString("yyyyMMddHHmmssfff"));
// buff.Append(now.ToString("yyyyMMddHHmmss"));
buff.Append(",");
buff.Append(line);
buff.Append("\r\n");
m_logFile.Write(buff.ToString());
}
}
}
catch (Exception e)
{
if (ErrorLogger != null)
{
ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
}
Enabled = false;
}
return;
}
}
}

View File

@ -40,6 +40,7 @@ using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Servers;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -31,7 +31,7 @@ using System.Collections.Generic;
using System.Reflection;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Services.Connectors;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -131,11 +131,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
m_enabled = true;
}
///<summary>
///
///</summary>
///<summary>
///
///</summary>
@ -149,10 +144,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
lock (m_scenes)
m_scenes[scene.RegionInfo.RegionID] = scene;
scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) UploadMapTile(s); };
}
///<summary>
///
///</summary>
@ -166,21 +160,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
}
#endregion ISharedRegionModule
void OnLoginsEnabled(string regionName)
{
Scene scene = null;
foreach (Scene s in m_scenes.Values)
if (s.RegionInfo.RegionName == regionName)
{
scene = s;
break;
}
if (scene != null)
UploadMapTile(scene);
}
///<summary>
///
///</summary>

View File

@ -129,18 +129,18 @@ namespace OpenSim.Region.CoreModules.World
switch (cmd[1])
{
case "enable":
scene.LoginsDisabled = false;
scene.LoginsEnabled = true;
MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName));
break;
case "disable":
scene.LoginsDisabled = true;
scene.LoginsEnabled = false;
MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName));
break;
case "status":
if (scene.LoginsDisabled)
MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName));
else
if (scene.LoginsEnabled)
MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName));
else
MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName));
break;
default:
MainConsole.Instance.Output("Syntax: login enable|disable|status");

View File

@ -37,7 +37,7 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -37,7 +37,7 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -119,17 +119,20 @@ namespace OpenSim.Region.CoreModules.World.Sound
m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
if (dis > 100.0) // Max audio distance
return;
float thisSpGain;
// Scale by distance
if (radius == 0)
gain = (float)((double)gain * ((100.0 - dis) / 100.0));
thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
else
gain = (float)((double)gain * ((radius - dis) / radius));
thisSpGain = (float)((double)gain * ((radius - dis) / radius));
sp.ControllingClient.SendTriggeredSound(
soundId, ownerID, objectID, parentID, handle, position, (float)gain);
soundId, ownerID, objectID, parentID, handle, position, thisSpGain);
});
}
}

View File

@ -42,6 +42,7 @@ using OpenMetaverse.Imaging;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;

View File

@ -25,14 +25,23 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using OpenSim.Framework;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IRegionReadyModule
{
void OarLoadingAlert(string msg);
/// <summary>
/// Trigger region ready status manually.
/// </summary>
/// <remarks>
/// This should be called by the scene if the IRegionReadyModule has set Scene.LoginLock == true
/// </remarks>
/// <param name='scene'></param>
void TriggerRegionReady(IScene scene);
}
}

View File

@ -40,8 +40,6 @@ namespace OpenSim.Region.Framework.Interfaces
/// </remarks>
public interface IScenePresence : ISceneAgent
{
PresenceType PresenceType { get; }
/// <summary>
/// Copy of the script states while the agent is in transit. This state may
/// need to be placed back in case of transfer fail.

View File

@ -67,6 +67,10 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="key"></param>
void DispatchReply(UUID scriptId, int code, string text, string key);
/// For constants
void RegisterConstant(string cname, object value);
object LookupModConstant(string cname);
// For use ONLY by the script API
void RaiseEvent(UUID script, string id, string module, string command, string key);
}

View File

@ -551,11 +551,5 @@ namespace OpenSim.Region.Framework.Scenes.Animation
SendAnimPack(animIDs, sequenceNums, objectIDs);
}
public void Close()
{
m_animations = null;
m_scenePresence = null;
}
}
}
}

View File

@ -500,15 +500,24 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void RegionHeartbeatEnd(Scene scene);
public event RegionHeartbeatEnd OnRegionHeartbeatEnd;
public delegate void LoginsEnabled(string regionName);
/// <summary>
/// This should only fire in all circumstances if the RegionReady module is active.
/// Fired when logins to a region are enabled or disabled.
/// </summary>
/// <remarks>
/// TODO: Fire this even when the RegionReady module is not active.
///
/// </remarks>
public event LoginsEnabled OnLoginsEnabled;
/// Fired
public event RegionLoginsStatusChange OnRegionLoginsStatusChange;
public delegate void RegionLoginsStatusChange(IScene scene);
/// <summary>
/// Fired when a region is considered ready for use.
/// </summary>
/// <remarks>
/// A region is considered ready when startup operations such as loading of scripts already on the region
/// have been completed.
/// </remarks>
public event Action<IScene> OnRegionReadyStatusChange;
public delegate void PrimsLoaded(Scene s);
public event PrimsLoaded OnPrimsLoaded;
@ -2502,21 +2511,42 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerLoginsEnabled (string regionName)
public void TriggerRegionLoginsStatusChange(IScene scene)
{
LoginsEnabled handler = OnLoginsEnabled;
RegionLoginsStatusChange handler = OnRegionLoginsStatusChange;
if ( handler != null)
if (handler != null)
{
foreach (LoginsEnabled d in handler.GetInvocationList())
foreach (RegionLoginsStatusChange d in handler.GetInvocationList())
{
try
{
d(regionName);
d(scene);
}
catch (Exception e)
{
m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}",
m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionLoginsStatusChange failed - continuing {0} - {1}",
e.Message, e.StackTrace);
}
}
}
}
public void TriggerRegionReadyStatusChange(IScene scene)
{
Action<IScene> handler = OnRegionReadyStatusChange;
if (handler != null)
{
foreach (Action<IScene> d in handler.GetInvocationList())
{
try
{
d(scene);
}
catch (Exception e)
{
m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionReadyStatusChange failed - continuing {0} - {1}",
e.Message, e.StackTrace);
}
}

View File

@ -39,7 +39,7 @@ using OpenSim.Framework.Communications;
using OpenSim.Framework.Console;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -811,16 +811,20 @@ namespace OpenSim.Region.Framework.Scenes
&& oldAgentID == LibraryService.LibraryRootFolder.Owner))
{
CreateNewInventoryItem(
remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType,
item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
remoteClient, item.CreatorId, item.CreatorData, newFolderID,
newName, item.Description, item.Flags, callbackID, asset, (sbyte)item.InvType,
item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions,
item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
}
else
{
// If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item.
if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) && (m_permissions.BypassPermissions() || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID)))
if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0)
&& (m_permissions.BypassPermissions()
|| m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID)))
{
CreateNewInventoryItem(
remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID,
remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Description, item.Flags, callbackID,
asset, (sbyte) item.InvType,
item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions,
item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
@ -885,32 +889,50 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary>
/// Create a new inventory item.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="folderID"></param>
/// <param name="callbackID"></param>
/// <param name="asset"></param>
/// <param name="invType"></param>
/// <param name="nextOwnerMask"></param>
public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID,
AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate)
/// <param name="remoteClient">Client creating this inventory item.</param>
/// <param name="creatorID"></param>
/// <param name="creatorData"></param>
/// <param name="folderID">UUID of folder in which this item should be placed.</param>
/// <param name="name">Item name.</para>
/// <param name="description">Item description.</param>
/// <param name="flags">Item flags</param>
/// <param name="callbackID">Generated by the client.</para>
/// <param name="asset">Asset to which this item refers.</param>
/// <param name="invType">Type of inventory item.</param>
/// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
/// <param name="creationDate">Unix timestamp at which this item was created.</param>
public void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
string name, string description, uint flags, uint callbackID,
AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate)
{
CreateNewInventoryItem(
remoteClient, creatorID, creatorData, folderID, name, flags, callbackID, asset, invType,
remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType,
(uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate);
}
/// <summary>
/// Create a new Inventory Item
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="folderID"></param>
/// <param name="callbackID"></param>
/// <param name="asset"></param>
/// <param name="invType"></param>
/// <param name="nextOwnerMask"></param>
/// <param name="creationDate"></param>
/// <param name="remoteClient">Client creating this inventory item.</param>
/// <param name="creatorID"></param>
/// <param name="creatorData"></param>
/// <param name="folderID">UUID of folder in which this item should be placed.</param>
/// <param name="name">Item name.</para>
/// <param name="description">Item description.</param>
/// <param name="flags">Item flags</param>
/// <param name="callbackID">Generated by the client.</para>
/// <param name="asset">Asset to which this item refers.</param>
/// <param name="invType">Type of inventory item.</param>
/// <param name="baseMask">Base permissions mask.</param>
/// <param name="currentMask">Current permissions mask.</param>
/// <param name="everyoneMask">Everyone permissions mask.</param>
/// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
/// <param name="groupMask">Group permissions mask.</param>
/// <param name="creationDate">Unix timestamp at which this item was created.</param>
private void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType,
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
{
InventoryItemBase item = new InventoryItemBase();
@ -919,8 +941,8 @@ namespace OpenSim.Region.Framework.Scenes
item.CreatorData = creatorData;
item.ID = UUID.Random();
item.AssetID = asset.FullID;
item.Description = asset.Description;
item.Name = name;
item.Description = description;
item.Flags = flags;
item.AssetType = asset.Type;
item.InvType = invType;
@ -1002,7 +1024,8 @@ namespace OpenSim.Region.Framework.Scenes
asset.Description = description;
CreateNewInventoryItem(
remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, 0, callbackID, asset, invType,
remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
name, description, 0, callbackID, asset, invType,
(uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All,
(uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch());
}

View File

@ -40,6 +40,7 @@ using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.Imaging;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Communications;
using OpenSim.Framework.Console;
@ -129,9 +130,10 @@ namespace OpenSim.Region.Framework.Scenes
public bool m_strictAccessControl = true;
public bool m_seeIntoBannedRegion = false;
public int MaxUndoCount = 5;
// Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
public bool LoginLock = false;
public bool LoginsDisabled = true;
public bool StartDisabled = false;
public bool LoadingPrims;
public IXfer XferManager;
@ -727,6 +729,8 @@ namespace OpenSim.Region.Framework.Scenes
{
IConfig startupConfig = m_config.Configs["Startup"];
StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
if (!m_useBackup)
@ -1229,15 +1233,17 @@ namespace OpenSim.Region.Framework.Scenes
avatar.ControllingClient.SendShutdownConnectionNotice();
});
// Stop updating the scene objects and agents.
m_shuttingDown = true;
// Wait here, or the kick messages won't actually get to the agents before the scene terminates.
// We also need to wait to avoid a race condition with the scene update loop which might not yet
// have checked ShuttingDown.
Thread.Sleep(500);
// Stop all client threads.
ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); });
// Stop updating the scene objects and agents.
m_shuttingDown = true;
m_log.Debug("[SCENE]: Persisting changed objects");
EventManager.TriggerSceneShuttingDown(this);
@ -1252,6 +1258,15 @@ namespace OpenSim.Region.Framework.Scenes
m_sceneGraph.Close();
if (PhysicsScene != null)
{
PhysicsScene phys = PhysicsScene;
// remove the physics engine from both Scene and SceneGraph
PhysicsScene = null;
phys.Dispose();
phys = null;
}
if (!GridService.DeregisterRegion(RegionInfo.RegionID))
m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
@ -1530,7 +1545,7 @@ namespace OpenSim.Region.Framework.Scenes
// landMS = Util.EnvironmentTickCountSubtract(ldMS);
//}
if (LoginsDisabled && Frame == 20)
if (!LoginsEnabled && Frame == 20)
{
// m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
@ -1538,31 +1553,34 @@ namespace OpenSim.Region.Framework.Scenes
// this is a rare case where we know we have just went through a long cycle of heap
// allocations, and there is no more work to be done until someone logs in
GC.Collect();
IConfig startupConfig = m_config.Configs["Startup"];
if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
if (!LoginLock)
{
if (!StartDisabled)
{
m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
LoginsEnabled = true;
}
m_sceneGridService.InformNeighborsThatRegionisUp(
RequestModuleInterface<INeighbourService>(), RegionInfo);
// Region ready should always be set
Ready = true;
}
else
{
// This handles a case of a region having no scripts for the RegionReady module
if (m_sceneGraph.GetActiveScriptsCount() == 0)
{
// need to be able to tell these have changed in RegionReady
LoginLock = false;
EventManager.TriggerLoginsEnabled(RegionInfo.RegionName);
// In this case, we leave it to the IRegionReadyModule to enable logins
// LoginLock can currently only be set by a region module implementation.
// If somehow this hasn't been done then the quickest way to bugfix is to see the
// NullReferenceException
IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>();
rrm.TriggerRegionReady(this);
}
// For RegionReady lockouts
if (!LoginLock)
{
m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
LoginsDisabled = false;
}
m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
}
else
{
StartDisabled = true;
LoginsDisabled = true;
}
}
}
@ -3477,25 +3495,31 @@ namespace OpenSim.Region.Framework.Scenes
if (AgentTransactionsModule != null)
AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
avatar.Close();
m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
m_log.Debug("[Scene] The avatar has left the building");
}
catch (Exception e)
{
m_log.Error(
string.Format("[SCENE]: Exception removing {0} from {1}, ", avatar.Name, RegionInfo.RegionName), e);
string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
}
finally
{
// Always clean these structures up so that any failure above doesn't cause them to remain in the
// scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
// the same cleanup exception continually.
// TODO: This should probably extend to the whole method, but we don't want to also catch the NRE
// since this would hide the underlying failure and other associated problems.
m_sceneGraph.RemoveScenePresence(agentID);
m_clientManager.Remove(agentID);
try
{
// Always clean these structures up so that any failure above doesn't cause them to remain in the
// scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
// the same cleanup exception continually.
m_sceneGraph.RemoveScenePresence(agentID);
m_clientManager.Remove(agentID);
avatar.Close();
}
catch (Exception e)
{
m_log.Error(
string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
}
}
//m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
@ -3609,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes
agent.startpos
);
if (LoginsDisabled)
if (!LoginsEnabled)
{
reason = "Logins Disabled";
return false;
@ -3666,8 +3690,8 @@ namespace OpenSim.Region.Framework.Scenes
// We have a zombie from a crashed session.
// Or the same user is trying to be root twice here, won't work.
// Kill it.
m_log.DebugFormat(
"[SCENE]: Zombie scene presence detected for {0} {1} in {2}",
m_log.WarnFormat(
"[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
sp.Name, sp.UUID, RegionInfo.RegionName);
sp.ControllingClient.Close();
@ -4657,6 +4681,23 @@ namespace OpenSim.Region.Framework.Scenes
return m_sceneGraph.GetScenePresence(localID);
}
/// <summary>
/// Gets all the scene presences in this scene.
/// </summary>
/// <remarks>
/// This method will return both root and child scene presences.
///
/// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not
/// involving creating a new List object.
/// </remarks>
/// <returns>
/// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene.
/// </returns>
public List<ScenePresence> GetScenePresences()
{
return new List<ScenePresence>(m_sceneGraph.GetScenePresences());
}
/// <summary>
/// Performs action on all avatars in the scene (root scene presences)
/// Avatars may be an NPC or a 'real' client.
@ -5775,5 +5816,21 @@ Environment.Exit(1);
{
GC.Collect();
}
// Wrappers to get physics modules retrieve assets. Has to be done this way
// because we can't assign the asset service to physics directly - at the
// time physics are instantiated it's not registered but it will be by
// the time the first prim exists.
public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback)
{
AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived);
}
private void PhysicsAssetReceived(string id, Object sender, AssetBase asset)
{
AssetReceivedDelegate callback = (AssetReceivedDelegate)sender;
callback(asset);
}
}
}

View File

@ -106,6 +106,42 @@ namespace OpenSim.Region.Framework.Scenes
protected readonly ClientManager m_clientManager = new ClientManager();
public bool LoginsEnabled
{
get
{
return m_loginsEnabled;
}
set
{
if (m_loginsEnabled != value)
{
m_loginsEnabled = value;
EventManager.TriggerRegionLoginsStatusChange(this);
}
}
}
private bool m_loginsEnabled;
public bool Ready
{
get
{
return m_ready;
}
set
{
if (m_ready != value)
{
m_ready = value;
EventManager.TriggerRegionReadyStatusChange(this);
}
}
}
private bool m_ready;
public float TimeDilation
{
get { return 1.0f; }

View File

@ -848,7 +848,7 @@ namespace OpenSim.Region.Framework.Scenes
/// pass a delegate to ForEachScenePresence.
/// </summary>
/// <returns></returns>
private List<ScenePresence> GetScenePresences()
protected internal List<ScenePresence> GetScenePresences()
{
return m_scenePresenceArray;
}

View File

@ -47,6 +47,48 @@ namespace OpenSim.Region.Framework.Scenes
public event RestartSim OnRestartSim;
/// <summary>
/// Fired when either all regions are ready for use or at least one region has become unready for use where
/// previously all regions were ready.
/// </summary>
public event Action<SceneManager> OnRegionsReadyStatusChange;
/// <summary>
/// Are all regions ready for use?
/// </summary>
public bool AllRegionsReady
{
get
{
return m_allRegionsReady;
}
private set
{
if (m_allRegionsReady != value)
{
m_allRegionsReady = value;
Action<SceneManager> handler = OnRegionsReadyStatusChange;
if (handler != null)
{
foreach (Action<SceneManager> d in handler.GetInvocationList())
{
try
{
d(this);
}
catch (Exception e)
{
m_log.ErrorFormat("[SCENE MANAGER]: Delegate for OnRegionsReadyStatusChange failed - continuing {0} - {1}",
e.Message, e.StackTrace);
}
}
}
}
}
}
private bool m_allRegionsReady;
private static SceneManager m_instance = null;
public static SceneManager Instance
{
@ -128,9 +170,11 @@ namespace OpenSim.Region.Framework.Scenes
public void Add(Scene scene)
{
scene.OnRestart += HandleRestart;
lock (m_localScenes)
m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
scene.OnRestart += HandleRestart;
scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange;
}
public void HandleRestart(RegionInfo rdata)
@ -138,12 +182,19 @@ namespace OpenSim.Region.Framework.Scenes
m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main");
int RegionSceneElement = -1;
m_localScenes.Remove(rdata.RegionID);
lock (m_localScenes)
m_localScenes.Remove(rdata.RegionID);
// Send signal to main that we're restarting this sim.
OnRestartSim(rdata);
}
private void HandleRegionReadyStatusChange(IScene scene)
{
lock (m_localScenes)
AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0;
}
public void SendSimOnlineNotification(ulong regionHandle)
{
RegionInfo Result = null;
@ -483,7 +534,8 @@ namespace OpenSim.Region.Framework.Scenes
public void CloseScene(Scene scene)
{
m_localScenes.Remove(scene.RegionInfo.RegionID);
lock (m_localScenes)
m_localScenes.Remove(scene.RegionInfo.RegionID);
scene.Close();
}

View File

@ -1991,7 +1991,7 @@ namespace OpenSim.Region.Framework.Scenes
try
{
if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
!m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things
m_scene.LoadingPrims) // Land may not be valid yet
{

View File

@ -110,15 +110,10 @@ namespace OpenSim.Region.Framework.Scenes
public UUID currentParcelUUID = UUID.Zero;
protected ScenePresenceAnimator m_animator;
/// <value>
/// The animator for this avatar
/// </value>
public ScenePresenceAnimator Animator
{
get { return m_animator; }
private set { m_animator = value; }
}
public ScenePresenceAnimator Animator { get; private set; }
/// <summary>
/// Attachments recorded on this avatar.
@ -2763,8 +2758,7 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
avatar.ControllingClient.SendAvatarDataImmediate(this);
if (Animator != null)
Animator.SendAnimPackToClient(avatar.ControllingClient);
Animator.SendAnimPackToClient(avatar.ControllingClient);
}
/// <summary>
@ -3440,6 +3434,16 @@ namespace OpenSim.Region.Framework.Scenes
if (IsChildAgent)
return;
//if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
// The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
// as of this comment the interval is set in AddToPhysicalScene
// if (m_updateCount > 0)
// {
Animator.UpdateMovementAnimations();
// m_updateCount--;
// }
CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
@ -3453,7 +3457,7 @@ namespace OpenSim.Region.Framework.Scenes
// m_lastColCount = coldata.Count;
// }
if (coldata.Count != 0 && Animator != null)
if (coldata.Count != 0)
{
switch (Animator.CurrentMovementAnimation)
{
@ -3565,7 +3569,7 @@ namespace OpenSim.Region.Framework.Scenes
ControllingClient.SendHealth(Health);
}
public void Close()
protected internal void Close()
{
// Clear known regions
KnownRegions = new Dictionary<ulong, string>();
@ -3581,9 +3585,6 @@ namespace OpenSim.Region.Framework.Scenes
// m_reprioritizationTimer.Dispose();
RemoveFromPhysicalScene();
if(Animator != null)
Animator.Close();
Animator = null;
}
public void AddAttachment(SceneObjectGroup gobj)

View File

@ -30,7 +30,7 @@ using System.Collections.Generic;
using System.Timers;
using OpenMetaverse.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.Framework.Scenes

View File

@ -53,48 +53,83 @@ namespace OpenSim.Region.Framework.Scenes.Tests
/// Scene presence tests
/// </summary>
[TestFixture]
public class ScenePresenceAgentTests
public class ScenePresenceAgentTests : OpenSimTestCase
{
public Scene scene, scene2, scene3;
public UUID agent1, agent2, agent3;
public static Random random;
public ulong region1,region2,region3;
public AgentCircuitData acd1;
public SceneObjectGroup sog1, sog2, sog3;
public TestClient testclient;
// public Scene scene, scene2, scene3;
// public UUID agent1, agent2, agent3;
// public static Random random;
// public ulong region1, region2, region3;
// public AgentCircuitData acd1;
// public TestClient testclient;
[TestFixtureSetUp]
public void Init()
// [TestFixtureSetUp]
// public void Init()
// {
//// TestHelpers.InMethod();
////
//// SceneHelpers sh = new SceneHelpers();
////
//// scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000);
//// scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000);
//// scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000);
////
//// ISharedRegionModule interregionComms = new LocalSimulationConnectorModule();
//// interregionComms.Initialise(new IniConfigSource());
//// interregionComms.PostInitialise();
//// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms);
//// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms);
//// SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms);
//
//// agent1 = UUID.Random();
//// agent2 = UUID.Random();
//// agent3 = UUID.Random();
//
//// region1 = scene.RegionInfo.RegionHandle;
//// region2 = scene2.RegionInfo.RegionHandle;
//// region3 = scene3.RegionInfo.RegionHandle;
// }
[Test]
public void TestCreateRootScenePresence()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
SceneHelpers sh = new SceneHelpers();
UUID spUuid = TestHelpers.ParseTail(0x1);
scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000);
scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000);
scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000);
TestScene scene = new SceneHelpers().SetupScene();
SceneHelpers.AddScenePresence(scene, spUuid);
ISharedRegionModule interregionComms = new LocalSimulationConnectorModule();
interregionComms.Initialise(new IniConfigSource());
interregionComms.PostInitialise();
SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms);
SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms);
SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms);
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
agent1 = UUID.Random();
agent2 = UUID.Random();
agent3 = UUID.Random();
random = new Random();
sog1 = SceneHelpers.CreateSceneObject(1, agent1);
scene.AddSceneObject(sog1);
sog2 = SceneHelpers.CreateSceneObject(1, agent1);
scene.AddSceneObject(sog2);
sog3 = SceneHelpers.CreateSceneObject(1, agent1);
scene.AddSceneObject(sog3);
ScenePresence sp = scene.GetScenePresence(spUuid);
Assert.That(sp, Is.Not.Null);
Assert.That(sp.IsChildAgent, Is.False);
Assert.That(sp.UUID, Is.EqualTo(spUuid));
region1 = scene.RegionInfo.RegionHandle;
region2 = scene2.RegionInfo.RegionHandle;
region3 = scene3.RegionInfo.RegionHandle;
Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
}
[Test]
public void TestCreateDuplicateRootScenePresence()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID spUuid = TestHelpers.ParseTail(0x1);
TestScene scene = new SceneHelpers().SetupScene();
SceneHelpers.AddScenePresence(scene, spUuid);
SceneHelpers.AddScenePresence(scene, spUuid);
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
ScenePresence sp = scene.GetScenePresence(spUuid);
Assert.That(sp, Is.Not.Null);
Assert.That(sp.IsChildAgent, Is.False);
Assert.That(sp.UUID, Is.EqualTo(spUuid));
}
[Test]
@ -106,9 +141,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestScene scene = new SceneHelpers().SetupScene();
ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
scene.IncomingCloseAgent(sp.UUID);
Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
@ -266,99 +298,99 @@ namespace OpenSim.Region.Framework.Scenes.Tests
// but things are synchronous among them. So there should be
// 3 threads in here.
//[Test]
public void T021_TestCrossToNewRegion()
{
TestHelpers.InMethod();
scene.RegisterRegionWithGrid();
scene2.RegisterRegionWithGrid();
// Adding child agent to region 1001
string reason;
scene2.NewUserConnection(acd1,0, out reason);
scene2.AddNewClient(testclient, PresenceType.User);
ScenePresence presence = scene.GetScenePresence(agent1);
presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true);
ScenePresence presence2 = scene2.GetScenePresence(agent1);
// Adding neighbour region caps info to presence2
string cap = presence.ControllingClient.RequestClientInfo().CapsPath;
presence2.AddNeighbourRegion(region1, cap);
Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region.");
Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region.");
// Cross to x+1
presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100);
presence.Update();
EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
// Mimicking communication between client and server, by waiting OK from client
// sent by TestClient.CrossRegion call. Originally, this is network comm.
if (!wh.WaitOne(5000,false))
{
presence.Update();
if (!wh.WaitOne(8000,false))
throw new ArgumentException("1 - Timeout waiting for signal/variable.");
}
// This is a TestClient specific method that fires OnCompleteMovementToRegion event, which
// would normally be fired after receiving the reply packet from comm. done on the last line.
testclient.CompleteMovement();
// Crossings are asynchronous
int timer = 10;
// Make sure cross hasn't already finished
if (!presence.IsInTransit && !presence.IsChildAgent)
{
// If not and not in transit yet, give it some more time
Thread.Sleep(5000);
}
// Enough time, should at least be in transit by now.
while (presence.IsInTransit && timer > 0)
{
Thread.Sleep(1000);
timer-=1;
}
Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1.");
Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected.");
Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent.");
// Cross Back
presence2.AbsolutePosition = new Vector3(-10, 3, 100);
presence2.Update();
if (!wh.WaitOne(5000,false))
{
presence2.Update();
if (!wh.WaitOne(8000,false))
throw new ArgumentException("2 - Timeout waiting for signal/variable.");
}
testclient.CompleteMovement();
if (!presence2.IsInTransit && !presence2.IsChildAgent)
{
// If not and not in transit yet, give it some more time
Thread.Sleep(5000);
}
// Enough time, should at least be in transit by now.
while (presence2.IsInTransit && timer > 0)
{
Thread.Sleep(1000);
timer-=1;
}
Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2.");
Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected.");
Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again.");
}
// public void T021_TestCrossToNewRegion()
// {
// TestHelpers.InMethod();
//
// scene.RegisterRegionWithGrid();
// scene2.RegisterRegionWithGrid();
//
// // Adding child agent to region 1001
// string reason;
// scene2.NewUserConnection(acd1,0, out reason);
// scene2.AddNewClient(testclient, PresenceType.User);
//
// ScenePresence presence = scene.GetScenePresence(agent1);
// presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true);
//
// ScenePresence presence2 = scene2.GetScenePresence(agent1);
//
// // Adding neighbour region caps info to presence2
//
// string cap = presence.ControllingClient.RequestClientInfo().CapsPath;
// presence2.AddNeighbourRegion(region1, cap);
//
// Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region.");
// Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region.");
//
// // Cross to x+1
// presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100);
// presence.Update();
//
// EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
//
// // Mimicking communication between client and server, by waiting OK from client
// // sent by TestClient.CrossRegion call. Originally, this is network comm.
// if (!wh.WaitOne(5000,false))
// {
// presence.Update();
// if (!wh.WaitOne(8000,false))
// throw new ArgumentException("1 - Timeout waiting for signal/variable.");
// }
//
// // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which
// // would normally be fired after receiving the reply packet from comm. done on the last line.
// testclient.CompleteMovement();
//
// // Crossings are asynchronous
// int timer = 10;
//
// // Make sure cross hasn't already finished
// if (!presence.IsInTransit && !presence.IsChildAgent)
// {
// // If not and not in transit yet, give it some more time
// Thread.Sleep(5000);
// }
//
// // Enough time, should at least be in transit by now.
// while (presence.IsInTransit && timer > 0)
// {
// Thread.Sleep(1000);
// timer-=1;
// }
//
// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1.");
// Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected.");
// Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent.");
//
// // Cross Back
// presence2.AbsolutePosition = new Vector3(-10, 3, 100);
// presence2.Update();
//
// if (!wh.WaitOne(5000,false))
// {
// presence2.Update();
// if (!wh.WaitOne(8000,false))
// throw new ArgumentException("2 - Timeout waiting for signal/variable.");
// }
// testclient.CompleteMovement();
//
// if (!presence2.IsInTransit && !presence2.IsChildAgent)
// {
// // If not and not in transit yet, give it some more time
// Thread.Sleep(5000);
// }
//
// // Enough time, should at least be in transit by now.
// while (presence2.IsInTransit && timer > 0)
// {
// Thread.Sleep(1000);
// timer-=1;
// }
//
// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2.");
// Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected.");
// Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again.");
// }
}
}

View File

@ -301,7 +301,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
sp.AbsolutePosition = preTeleportPosition;
// Make sceneB refuse CreateAgent
sceneB.LoginsDisabled = true;
sceneB.LoginsEnabled = false;
sceneA.RequestTeleportLocation(
sp.ControllingClient,

View File

@ -38,6 +38,7 @@ using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server

View File

@ -34,6 +34,7 @@ using System.Text;
using System.Threading;
using log4net;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server

View File

@ -35,7 +35,7 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.ClientStack.LindenUDP;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
@ -81,18 +81,6 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
lock (m_scenes)
m_scenes[scene.RegionInfo.RegionID] = scene;
scene.AddCommand(
"Comms", this, "image queues clear",
"image queues clear <first-name> <last-name>",
"Clear the image queues (textures downloaded via UDP) for a particular client.",
(mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd)));
scene.AddCommand(
"Comms", this, "image queues show",
"image queues show <first-name> <last-name>",
"Show the image queues (textures downloaded via UDP) for a particular client.",
(mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd)));
scene.AddCommand(
"Comms", this, "show pqueues",
"show pqueues [full]",
@ -105,8 +93,15 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
"Comms", this, "show queues",
"show queues [full]",
"Show queue data for each client",
"Without the 'full' option, only root agents are shown."
+ " With the 'full' option child agents are also shown.",
"Without the 'full' option, only root agents are shown.\n"
+ "With the 'full' option child agents are also shown.\n\n"
+ "Type - Rt is a root (avatar) client whilst cd is a child (neighbour interacting) client.\n"
+ "Since Last In - Time in milliseconds since last packet received.\n"
+ "Pkts In - Number of packets processed from the client.\n"
+ "Pkts Out - Number of packets sent to the client.\n"
+ "Pkts Resent - Number of packets resent to the client.\n"
+ "Bytes Unacked - Number of bytes transferred to the client that are awaiting acknowledgement.\n"
+ "Q Pkts * - Number of packets of various types (land, wind, etc.) to be sent to the client that are waiting for available bandwidth.\n",
(mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd)));
scene.AddCommand(
@ -114,6 +109,12 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
"show image queues <first-name> <last-name>",
"Show the image queues (textures downloaded via UDP) for a particular client.",
(mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd)));
scene.AddCommand(
"Comms", this, "clear image queues",
"clear image queues <first-name> <last-name>",
"Clear the image queues (textures downloaded via UDP) for a particular client.",
(mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd)));
scene.AddCommand(
"Comms", this, "show throttles",
@ -373,17 +374,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
int maxNameLength = 18;
int maxRegionNameLength = 14;
int maxTypeLength = 4;
int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
int totalInfoFieldsLength
= maxNameLength + columnPadding
+ maxRegionNameLength + columnPadding
+ maxTypeLength + columnPadding;
report.Append(GetColumnEntry("User", maxNameLength, columnPadding));
report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding));
report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
report.AppendFormat(
"{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n",
"{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n",
"Since",
"Pkts",
"Pkts",
"Pkts",
"Pkts",
"Bytes",
"Q Pkts",
"Q Pkts",
@ -396,7 +402,8 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
report.AppendFormat(
"{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n",
"{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n",
"Last In",
"In",
"Out",
"Resent",
@ -417,22 +424,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
scene.ForEachClient(
delegate(IClientAPI client)
{
bool isChild = client.SceneAgent.IsChildAgent;
if (isChild && !showChildren)
return;
string name = client.Name;
if (pname != "" && name != pname)
return;
string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
if (client is IStatsCollector)
{
bool isChild = client.SceneAgent.IsChildAgent;
if (isChild && !showChildren)
return;
string name = client.Name;
if (pname != "" && name != pname)
return;
string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
IStatsCollector stats = (IStatsCollector)client;
report.AppendLine(stats.Report());

View File

@ -36,7 +36,7 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.ClientStack.LindenUDP;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -36,7 +36,7 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.ClientStack.LindenUDP;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -37,6 +37,7 @@ using OpenMetaverse;
using log4net;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

View File

@ -37,7 +37,7 @@ using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.ClientStack.LindenUDP;
using OpenSim.Region.CoreModules.Avatar.Friends;
using OpenSim.Region.Framework.Interfaces;

View File

@ -47,7 +47,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")]
public class PhysicsParameters : ISharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static string LogHeader = "[PHYSICS PARAMETERS]";
private List<Scene> m_scenes = new List<Scene>();

View File

@ -31,16 +31,14 @@ using System.Reflection;
using System.Net;
using System.IO;
using System.Text;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
{
@ -50,16 +48,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IConfig m_config = null;
private bool m_ScriptRez;
private bool m_firstEmptyCompileQueue;
private bool m_oarFileLoading;
private bool m_lastOarLoadedOk;
private int m_channelNotify = -1000;
private bool m_enabled = false;
private bool m_disable_logins = false;
private bool m_disable_logins;
private string m_uri = string.Empty;
Scene m_scene = null;
Scene m_scene;
#region INonSharedRegionModule interface
@ -93,53 +90,40 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
m_scene.RegisterModuleInterface<IRegionReadyModule>(this);
m_ScriptRez = false;
m_firstEmptyCompileQueue = true;
m_oarFileLoading = false;
m_lastOarLoadedOk = true;
m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded;
m_scene.EventManager.OnRezScript += OnRezScript;
m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName);
if (m_disable_logins == true)
if (m_disable_logins)
{
scene.LoginLock = true;
scene.LoginsDisabled = true;
m_log.InfoFormat("[RegionReady]: Region {0} - logins disabled during initialization.",m_scene.RegionInfo.RegionName);
m_scene.LoginLock = true;
m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
if(m_uri != string.Empty)
m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name);
if (m_uri != string.Empty)
{
RRAlert("disabled");
}
}
}
void OnRezScript (uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
{
if (!m_ScriptRez)
{
m_ScriptRez = true;
m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
m_scene.EventManager.OnRezScript -= OnRezScript;
}
}
public void RemoveRegion(Scene scene)
{
if (!m_enabled)
return;
m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded;
m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled;
if(m_uri != string.Empty)
{
if (m_disable_logins)
m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
if (m_uri != string.Empty)
RRAlert("shutdown");
}
m_scene = null;
}
@ -159,7 +143,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
#endregion
void OnEmptyScriptCompileQueue(int numScriptsFailed, string message)
{
m_log.DebugFormat("[RegionReady]: Script compile queue empty!");
@ -193,75 +176,80 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
m_scene.RegionInfo.RegionName, c.Message, m_channelNotify);
m_scene.EventManager.TriggerOnChatBroadcast(this, c);
m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName);
m_scene.SceneGridService.InformNeighborsThatRegionisUp(m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo);
TriggerRegionReady(m_scene);
}
}
void OnOarFileLoaded(Guid requestId, string message)
{
m_oarFileLoading = true;
if (message==String.Empty)
{
m_lastOarLoadedOk = true;
} else {
}
else
{
m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message);
m_lastOarLoadedOk = false;
}
}
// This will be triggerd by Scene if we have no scripts
// m_ScriptsRezzing will be false if there were none
// else it will be true and we should wait on the
// empty compile queue
void OnLoginsEnabled(string regionName)
/// <summary>
/// This will be triggered by Scene directly if it contains no scripts on startup. Otherwise it is triggered
/// when the script compile queue is empty after initial region startup.
/// </summary>
/// <param name='scene'></param>
public void TriggerRegionReady(IScene scene)
{
if (m_disable_logins == true)
m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
m_scene.LoginLock = false;
if (!m_scene.StartDisabled)
{
if (m_scene.StartDisabled == false)
{
m_scene.LoginsDisabled = false;
m_scene.LoginLock = false;
m_scene.LoginsEnabled = true;
m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
// m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
// m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
// m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
// m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
m_log.InfoFormat(
"[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
if (m_uri != string.Empty)
{
RRAlert("enabled");
}
}
m_log.InfoFormat(
"[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
}
m_scene.SceneGridService.InformNeighborsThatRegionisUp(
m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo);
if (m_uri != string.Empty)
{
RRAlert("enabled");
}
m_scene.Ready = true;
}
public void OarLoadingAlert(string msg)
{
// Let's bypass this for now until some better feedback can be established
//
return;
if (msg == "load")
{
m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded;
m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
m_scene.EventManager.OnRezScript += OnRezScript;
m_oarFileLoading = true;
m_firstEmptyCompileQueue = true;
m_scene.LoginsDisabled = true;
m_scene.LoginLock = true;
if ( m_uri != string.Empty )
{
RRAlert("loading oar");
RRAlert("disabled");
}
}
// if (msg == "load")
// {
// m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
// m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded;
// m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
// m_scene.EventManager.OnRezScript += OnRezScript;
// m_oarFileLoading = true;
// m_firstEmptyCompileQueue = true;
//
// m_scene.LoginsDisabled = true;
// m_scene.LoginLock = true;
// if ( m_uri != string.Empty )
// {
// RRAlert("loading oar");
// RRAlert("disabled");
// }
// }
}
public void RRAlert(string status)

View File

@ -46,6 +46,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<string,object> m_constants = new Dictionary<string,object>();
#region ScriptInvocation
protected class ScriptInvocationData
{
@ -269,6 +271,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
Delegate fn = LookupScriptInvocation(fname);
return fn.DynamicInvoke(olist.ToArray());
}
/// <summary>
/// Operation to for a region module to register a constant to be used
/// by the script engine
/// </summary>
public void RegisterConstant(string cname, object value)
{
m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
lock (m_constants)
{
m_constants.Add(cname,value);
}
}
/// <summary>
/// Operation to check for a registered constant
/// </summary>
public object LookupModConstant(string cname)
{
// m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname);
lock (m_constants)
{
object value = null;
if (m_constants.TryGetValue(cname,out value))
return value;
}
return null;
}
#endregion
}

View File

@ -41,7 +41,7 @@ public class BSCharacter : PhysicsActor
private BSScene _scene;
private String _avName;
private bool _stopped;
// private bool _stopped;
private Vector3 _size;
private Vector3 _scale;
private PrimitiveBaseShape _pbs;
@ -134,9 +134,9 @@ public class BSCharacter : PhysicsActor
{
base.RequestPhysicsterseUpdate();
}
// No one calls this method so I don't know what it could possibly mean
public override bool Stopped {
get { return _stopped; }
get { return false; }
}
public override Vector3 Size {
get { return _size; }
@ -391,52 +391,47 @@ public class BSCharacter : PhysicsActor
_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 world that things have changed.
public void UpdateProperties(EntityProperties entprop)
{
/*
bool changed = false;
if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) {
// we assign to the local variables so the normal set action does not happen
if (_position != entprop.Position) {
_position = entprop.Position;
changed = true;
}
if (_orientation != entprop.Rotation) {
_orientation = entprop.Rotation;
changed = true;
}
if (_velocity != entprop.Velocity) {
_velocity = entprop.Velocity;
changed = true;
}
if (_acceleration != entprop.Acceleration) {
_acceleration = entprop.Acceleration;
changed = true;
}
if (_rotationalVelocity != entprop.RotationalVelocity) {
_rotationalVelocity = entprop.RotationalVelocity;
changed = true;
}
if (changed) {
// 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 code in the heartbeat
// loop that updates avatars.
// base.RequestPhysicsterseUpdate();
}
}
else {
// we assign to the local variables so the normal set action does not happen
if (_position != entprop.Position) {
_position = entprop.Position;
changed = true;
}
if (_orientation != entprop.Rotation) {
_orientation = entprop.Rotation;
changed = true;
}
if (_velocity != entprop.Velocity) {
_velocity = entprop.Velocity;
changed = true;
}
if (_acceleration != entprop.Acceleration) {
_acceleration = entprop.Acceleration;
changed = true;
}
if (_rotationalVelocity != entprop.RotationalVelocity) {
_rotationalVelocity = entprop.RotationalVelocity;
changed = true;
}
if (changed) {
// 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 code in the heartbeat
// loop that updates avatars.
// base.RequestPhysicsterseUpdate();
}
*/
_position = entprop.Position;
_orientation = entprop.Rotation;
_velocity = entprop.Velocity;
_acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity;
// Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop.
// base.RequestPhysicsterseUpdate();
}
// Called by the scene when a collision with this object is reported

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public class BSConstraint : IDisposable
{
private BulletSim m_world;
private BulletBody m_body1;
private BulletBody m_body2;
private BulletConstraint m_constraint;
private bool m_enabled = false;
public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot
)
{
m_world = world;
m_body1 = obj1;
m_body2 = obj2;
m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
frame1, frame1rot,
frame2, frame2rot,
true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/));
m_enabled = true;
}
public void Dispose()
{
if (m_enabled)
{
// BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
m_enabled = false;
}
}
public BulletBody Body1 { get { return m_body1; } }
public BulletBody Body2 { get { return m_body2; } }
public bool SetLinearLimits(Vector3 low, Vector3 high)
{
bool ret = false;
if (m_enabled)
ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high);
return ret;
}
public bool SetAngularLimits(Vector3 low, Vector3 high)
{
bool ret = false;
if (m_enabled)
ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high);
return ret;
}
public bool SetCFMAndERP(float cfm, float erp)
{
bool ret = true;
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
return ret;
}
public bool UseFrameOffset(bool useOffset)
{
bool ret = false;
float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
if (m_enabled)
ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
return ret;
}
public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
{
bool ret = false;
float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
if (m_enabled)
ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
return ret;
}
public bool CalculateTransforms()
{
bool ret = false;
if (m_enabled)
{
BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
ret = true;
}
return ret;
}
}
}

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using log4net;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public class BSConstraintCollection : IDisposable
{
// private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
delegate bool ConstraintAction(BSConstraint constrain);
private List<BSConstraint> m_constraints;
private BulletSim m_world;
public BSConstraintCollection(BulletSim world)
{
m_world = world;
m_constraints = new List<BSConstraint>();
}
public void Dispose()
{
this.Clear();
}
public void Clear()
{
foreach (BSConstraint cons in m_constraints)
{
cons.Dispose();
}
m_constraints.Clear();
}
public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot)
{
BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
this.AddConstraint(constrain);
return constrain;
}
public bool AddConstraint(BSConstraint cons)
{
// There is only one constraint between any bodies. Remove any old just to make sure.
RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
m_constraints.Add(cons);
return true;
}
// Get the constraint between two bodies. There can be only one.
// Return 'true' if a constraint was found.
public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint)
{
bool found = false;
BSConstraint foundConstraint = null;
uint lookingID1 = body1.ID;
uint lookingID2 = body2.ID;
ForEachConstraint(delegate(BSConstraint constrain)
{
if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
|| (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
{
foundConstraint = constrain;
found = true;
}
return found;
});
returnConstraint = foundConstraint;
return found;
}
// Remove any constraint between the passed bodies.
// Presumed there is only one such constraint possible.
// Return 'true' if a constraint was found and destroyed.
public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
{
// return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
bool ret = false;
BSConstraint constrain;
if (this.TryGetConstraint(body1, body2, out constrain))
{
// remove the constraint from our collection
m_constraints.Remove(constrain);
// tell the engine that all its structures need to be freed
constrain.Dispose();
// we destroyed something
ret = true;
}
return ret;
}
// Remove all constraints that reference the passed body.
// Return 'true' if any constraints were destroyed.
public bool RemoveAndDestroyConstraint(BulletBody body1)
{
// return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
List<BSConstraint> toRemove = new List<BSConstraint>();
uint lookingID = body1.ID;
ForEachConstraint(delegate(BSConstraint constrain)
{
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
{
toRemove.Add(constrain);
}
return false;
});
lock (m_constraints)
{
foreach (BSConstraint constrain in toRemove)
{
m_constraints.Remove(constrain);
constrain.Dispose();
}
}
return (toRemove.Count > 0);
}
public bool RecalculateAllConstraints()
{
foreach (BSConstraint constrain in m_constraints)
{
constrain.CalculateTransforms();
}
return true;
}
// Lock the constraint list and loop through it.
// The constraint action returns 'true' if it wants the loop aborted.
private void ForEachConstraint(ConstraintAction action)
{
lock (m_constraints)
{
foreach (BSConstraint constrain in m_constraints)
{
if (action(constrain))
break;
}
}
}
}
}

View File

@ -57,7 +57,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private int frcount = 0; // Used to limit dynamics debug output to
// every 100th frame
// private BSScene m_parentScene = null;
private BSPrim m_prim; // the prim this dynamic controller belongs to
// Vehicle properties
@ -131,8 +130,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_type = Vehicle.TYPE_NONE;
}
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
{
DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
switch (pParam)
{
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
@ -229,8 +229,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
}//end ProcessFloatVehicleParam
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
{
DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
switch (pParam)
{
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@ -265,6 +266,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
{
DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
switch (pParam)
{
case Vehicle.REFERENCE_FRAME:
@ -278,6 +280,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
internal void ProcessVehicleFlags(int pParam, bool remove)
{
DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
if (remove)
{
if (pParam == -1)
@ -434,6 +437,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
internal void ProcessTypeChange(Vehicle pType)
{
DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
// Set Defaults For Type
m_type = pType;
switch (pType)
@ -594,11 +598,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
break;
}
}//end SetDefaultsForType
internal void Step(float pTimestep, BSScene pParentScene)
internal void Step(float pTimestep)
{
if (m_type == Vehicle.TYPE_NONE) return;
@ -606,21 +609,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (frcount > 100)
frcount = 0;
MoveLinear(pTimestep, pParentScene);
MoveLinear(pTimestep);
MoveAngular(pTimestep);
LimitRotation(pTimestep);
DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}",
m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
}// end Step
private void MoveLinear(float pTimestep, BSScene _pParentScene)
private void MoveLinear(float pTimestep)
{
if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant
// requested m_linearMotorDirection is significant
// if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
if (m_linearMotorDirection.LengthSquared() > 0.0001f)
{
Vector3 origDir = m_linearMotorDirection;
Vector3 origVel = m_lastLinearVelocityVector;
// add drive to body
Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector?
// Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale);
// lastLinearVelocityVector is the current body velocity vector?
// RA: Not sure what the *10 is for. A correction for pTimestep?
// m_lastLinearVelocityVector += (addAmount*10);
m_lastLinearVelocityVector += addAmount;
// This will work temporarily, but we really need to compare speed on an axis
// KF: Limit body velocity to applied velocity?
// Limit the velocity vector to less than the last set linear motor direction
if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
@ -630,76 +646,93 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// decay applied velocity
Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
//Console.WriteLine("decay: " + decayfraction);
m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
//Console.WriteLine("actual: " + m_linearMotorDirection);
/*
Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
m_lastLinearVelocityVector += addAmount;
float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
m_linearMotorDirection *= decayfraction;
*/
DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
}
else
{ // requested is not significant
// if what remains of applied is small, zero it.
if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
m_lastLinearVelocityVector = Vector3.Zero;
{
// if what remains of applied is small, zero it.
// if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
// m_lastLinearVelocityVector = Vector3.Zero;
m_linearMotorDirection = Vector3.Zero;
m_lastLinearVelocityVector = Vector3.Zero;
}
// convert requested object velocity to world-referenced vector
m_dir = m_lastLinearVelocityVector;
Quaternion rot = m_prim.Orientation;
Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
m_dir *= rotq; // apply obj rotation to velocity vector
Quaternion rotq = m_prim.Orientation;
m_dir = m_lastLinearVelocityVector * rotq;
// add Gravity andBuoyancy
// Add the various forces into m_dir which will be our new direction vector (velocity)
// add Gravity and Buoyancy
// KF: So far I have found no good method to combine a script-requested
// .Z velocity and gravity. Therefore only 0g will used script-requested
// .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
Vector3 grav = Vector3.Zero;
// There is some gravity, make a gravity force vector
// that is applied after object velocity.
float objMass = m_prim.Mass;
// There is some gravity, make a gravity force vector that is applied after object velocity.
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
grav.Z = _pParentScene.DefaultGravity.Z * objMass * (1f - m_VehicleBuoyancy);
grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy);
// Preserve the current Z velocity
Vector3 vel_now = m_prim.Velocity;
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
Vector3 pos = m_prim.Position;
Vector3 posChange = pos;
// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
Vector3 posChange = new Vector3();
posChange.X = pos.X - m_lastPositionVector.X;
posChange.Y = pos.Y - m_lastPositionVector.Y;
posChange.Z = pos.Z - m_lastPositionVector.Z;
double Zchange = Math.Abs(posChange.Z);
if (m_BlockingEndPoint != Vector3.Zero)
{
bool changed = false;
if (pos.X >= (m_BlockingEndPoint.X - (float)1))
{
pos.X -= posChange.X + 1;
m_prim.Position = pos;
changed = true;
}
if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
{
pos.Y -= posChange.Y + 1;
m_prim.Position = pos;
changed = true;
}
if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
{
pos.Z -= posChange.Z + 1;
m_prim.Position = pos;
changed = true;
}
if (pos.X <= 0)
{
pos.X += posChange.X + 1;
m_prim.Position = pos;
changed = true;
}
if (pos.Y <= 0)
{
pos.Y += posChange.Y + 1;
changed = true;
}
if (changed)
{
m_prim.Position = pos;
DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
}
}
if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y))
// If below the terrain, move us above the ground a little.
if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
{
pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2;
pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
m_prim.Position = pos;
DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
}
// Check if hovering
@ -708,11 +741,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// We should hover, get the target height
if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
{
m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight;
m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
}
if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
{
m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
}
if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
{
@ -746,6 +779,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
}
DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
// m_VhoverTimescale = 0f; // time to acheive height
// pTimestep is time since last frame,in secs
@ -774,12 +809,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
grav.Z = (float)(grav.Z * 1.125);
}
float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
float postemp = (pos.Z - terraintemp);
if (postemp > 2.5f)
{
grav.Z = (float)(grav.Z * 1.037125);
}
DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
//End Experimental Values
}
if ((m_flags & (VehicleFlag.NO_X)) != 0)
@ -800,32 +836,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Apply velocity
m_prim.Velocity = m_dir;
// apply gravity force
m_prim.Force = grav;
// Why is this set here? The physics engine already does gravity.
// m_prim.AddForce(grav, false);
// m_prim.Force = grav;
// apply friction
// Apply friction
Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
} // end MoveLinear()
private void MoveAngular(float pTimestep)
{
/*
private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
private int m_angularMotorApply = 0; // application frame counter
private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down)
private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
*/
// m_angularMotorDirection // angular velocity requested by LSL motor
// m_angularMotorApply // application frame counter
// m_angularMotorVelocity // current angular motor velocity (ramps up and down)
// m_angularMotorTimescale // motor angular velocity ramp up rate
// m_angularMotorDecayTimescale // motor angular velocity decay rate
// m_angularFrictionTimescale // body angular velocity decay rate
// m_lastAngularVelocity // what was last applied to body
// Get what the body is doing, this includes 'external' influences
Vector3 angularVelocity = m_prim.RotationalVelocity;
// Vector3 angularVelocity = Vector3.Zero;
if (m_angularMotorApply > 0)
{
// Rather than snapping the angular motor velocity from the old value to
// a newly set velocity, this routine steps the value from the previous
// value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
// There are m_angularMotorApply steps.
Vector3 origAngularVelocity = m_angularMotorVelocity;
// ramp up to new value
// current velocity += error / (time to get there / step interval)
// requested speed - last motor speed
@ -833,23 +876,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
// velocity may still be acheived.
}
else
{
// no motor recently applied, keep the body velocity
/* m_angularMotorVelocity.X = angularVelocity.X;
m_angularMotorVelocity.Y = angularVelocity.Y;
m_angularMotorVelocity.Z = angularVelocity.Z; */
// No motor recently applied, keep the body velocity
// and decay the velocity
m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
} // end motor section
// Vertical attractor section
Vector3 vertattr = Vector3.Zero;
if (m_verticalAttractionTimescale < 300)
{
float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
@ -871,7 +912,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Error is 0 (no error) to +/- 2 (max error)
// scale it by VAservo
verterr = verterr * VAservo;
//if (frcount == 0) Console.WriteLine("VAerr=" + verterr);
// As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
// Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
@ -884,11 +924,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
vertattr.X += bounce * angularVelocity.X;
vertattr.Y += bounce * angularVelocity.Y;
DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
m_prim.LocalID, verterr, bounce, vertattr);
} // else vertical attractor is off
// m_lastVertAttractor = vertattr;
// m_lastVertAttractor = vertattr;
// Bank section tba
// Deflection section tba
// Sum velocities
@ -898,11 +942,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
m_lastAngularVelocity.X = 0;
m_lastAngularVelocity.Y = 0;
DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
}
if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
{
m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
}
// apply friction
@ -912,10 +958,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Apply to the body
m_prim.RotationalVelocity = m_lastAngularVelocity;
DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
} //end MoveAngular
internal void LimitRotation(float timestep)
{
Quaternion rotq = m_prim.Orientation; // rotq = rotation of object
Quaternion rotq = m_prim.Orientation;
Quaternion m_rot = rotq;
bool changed = false;
if (m_RollreferenceFrame != Quaternion.Identity)
@ -923,18 +971,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (rotq.X >= m_RollreferenceFrame.X)
{
m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
changed = true;
}
if (rotq.Y >= m_RollreferenceFrame.Y)
{
m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
changed = true;
}
if (rotq.X <= -m_RollreferenceFrame.X)
{
m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
changed = true;
}
if (rotq.Y <= -m_RollreferenceFrame.Y)
{
m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
changed = true;
}
changed = true;
}
@ -944,8 +996,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_rot.Y = 0;
changed = true;
}
if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
{
m_rot.X = 0;
m_rot.Y = 0;
changed = true;
}
if (changed)
m_prim.Orientation = m_rot;
DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
}
// Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args)
{
if (m_prim.Scene.VehicleLoggingEnabled)
m_prim.Scene.PhysicsLogging.Write(msg, args);
}
}
}

View File

@ -0,0 +1,352 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyrightD
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using OMV = OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public class BSLinkset
{
private static string LogHeader = "[BULLETSIM LINKSET]";
private BSPrim m_linksetRoot;
public BSPrim Root { get { return m_linksetRoot; } }
private BSScene m_scene;
private List<BSPrim> m_children;
// We lock the diddling of linkset classes to prevent any badness.
// This locks the modification of the instances of this class. Changes
// to the physical representation is done via the tainting mechenism.
private object m_linksetActivityLock = new Object();
// We keep the prim's mass in the linkset structure since it could be dependent on other prims
private float m_mass;
public float LinksetMass
{
get
{
m_mass = ComputeLinksetMass();
return m_mass;
}
}
public OMV.Vector3 CenterOfMass
{
get { return ComputeLinksetCenterOfMass(); }
}
public OMV.Vector3 GeometricCenter
{
get { return ComputeLinksetGeometricCenter(); }
}
public BSLinkset(BSScene scene, BSPrim parent)
{
// A simple linkset of one (no children)
m_scene = scene;
m_linksetRoot = parent;
m_children = new List<BSPrim>();
m_mass = parent.MassRaw;
}
// Link to a linkset where the child knows the parent.
// Parent changing should not happen so do some sanity checking.
// We return the parent's linkset so the child can track it's membership.
public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent)
{
lock (m_linksetActivityLock)
{
parent.Linkset.AddChildToLinkset(child);
}
return parent.Linkset;
}
public BSLinkset RemoveMeFromLinkset(BSPrim child)
{
lock (m_linksetActivityLock)
{
if (IsRoot(child))
{
// if root of linkset, take the linkset apart
while (m_children.Count > 0)
{
// Note that we don't do a foreach because the remove routine
// takes it out of the list.
RemoveChildFromLinkset(m_children[0]);
}
m_children.Clear(); // just to make sure
}
else
{
// Just removing a child from an existing linkset
RemoveChildFromLinkset(child);
}
}
// The child is down to a linkset of just itself
return new BSLinkset(m_scene, child);
}
// An existing linkset had one of its members rebuilt or something.
// Go through the linkset and rebuild the pointers to the bodies of the linkset members.
public BSLinkset RefreshLinkset(BSPrim requestor)
{
BSLinkset ret = requestor.Linkset;
lock (m_linksetActivityLock)
{
System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
if (aPtr == System.IntPtr.Zero)
{
// That's odd. We can't find the root of the linkset.
// The linkset is somehow dead. The requestor is now a member of a linkset of one.
DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID);
ret = RemoveMeFromLinkset(m_linksetRoot);
}
else
{
// Reconstruct the pointer to the body of the linkset root.
DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr);
m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr);
List<BSPrim> toRemove = new List<BSPrim>();
foreach (BSPrim bsp in m_children)
{
aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID);
if (aPtr == System.IntPtr.Zero)
{
toRemove.Add(bsp);
}
else
{
// Reconstruct the pointer to the body of the linkset root.
DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr);
bsp.Body = new BulletBody(bsp.LocalID, aPtr);
}
}
foreach (BSPrim bsp in toRemove)
{
RemoveChildFromLinkset(bsp);
}
}
}
return ret;
}
// Return 'true' if the passed object is the root object of this linkset
public bool IsRoot(BSPrim requestor)
{
return (requestor.LocalID == m_linksetRoot.LocalID);
}
// Return 'true' if this linkset has any children (more than the root member)
public bool HasAnyChildren { get { return (m_children.Count > 0); } }
// Return 'true' if this child is in this linkset
public bool HasChild(BSPrim child)
{
bool ret = false;
foreach (BSPrim bp in m_children)
{
if (child.LocalID == bp.LocalID)
{
ret = true;
break;
}
}
return ret;
}
private float ComputeLinksetMass()
{
float mass = m_linksetRoot.MassRaw;
foreach (BSPrim bp in m_children)
{
mass += bp.MassRaw;
}
return mass;
}
private OMV.Vector3 ComputeLinksetCenterOfMass()
{
OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
float totalMass = m_linksetRoot.MassRaw;
foreach (BSPrim bp in m_children)
{
com += bp.Position * bp.MassRaw;
totalMass += bp.MassRaw;
}
com /= totalMass;
return com;
}
private OMV.Vector3 ComputeLinksetGeometricCenter()
{
OMV.Vector3 com = m_linksetRoot.Position;
foreach (BSPrim bp in m_children)
{
com += bp.Position * bp.MassRaw;
}
com /= m_children.Count + 1;
return com;
}
// I am the root of a linkset and a new child is being added
public void AddChildToLinkset(BSPrim pchild)
{
BSPrim child = pchild;
if (!HasChild(child))
{
m_children.Add(child);
m_scene.TaintedObject(delegate()
{
DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child
});
}
return;
}
// I am the root of a linkset and one of my children is being removed.
// Safe to call even if the child is not really in my linkset.
public void RemoveChildFromLinkset(BSPrim pchild)
{
BSPrim child = pchild;
if (m_children.Remove(child))
{
m_scene.TaintedObject(delegate()
{
DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
if (m_children.Count == 0)
{
// if the linkset is empty, make sure all linkages have been removed
PhysicallyUnlinkAllChildrenFromRoot();
}
else
{
PhysicallyUnlinkAChildFromRoot(pchild);
}
});
}
else
{
// This will happen if we remove the root of the linkset first. Non-fatal occurance.
// m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
}
return;
}
// Create a constraint between me (root of linkset) and the passed prim (the child).
// Called at taint time!
private void PhysicallyLinkAChildToRoot(BSPrim childPrim)
{
// Zero motion for children so they don't interpolate
childPrim.ZeroMotion();
// relative position normalized to the root prim
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation);
OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation;
// relative rotation of the child to the parent
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
// create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
// DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
BSConstraint constrain = m_scene.Constraints.CreateConstraint(
m_scene.World, m_linksetRoot.Body, childPrim.Body,
// childRelativePosition,
// childRelativeRotation,
OMV.Vector3.Zero,
OMV.Quaternion.Identity,
OMV.Vector3.Zero,
OMV.Quaternion.Identity
);
constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
// tweek the constraint to increase stability
constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset));
constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor),
m_scene.Params.linkConstraintTransMotorMaxVel,
m_scene.Params.linkConstraintTransMotorMaxForce);
constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP);
}
// Remove linkage between myself and a particular child
// Called at taint time!
private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim)
{
DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
LogHeader, m_linksetRoot.LocalID, childPrim.LocalID);
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
// BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body);
}
// Remove linkage between myself and any possible children I might have
// Called at taint time!
private void PhysicallyUnlinkAllChildrenFromRoot()
{
// DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID);
m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body);
// BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
}
// Invoke the detailed logger and output something if it's enabled.
private void DebugLog(string msg, params Object[] args)
{
m_scene.Logger.DebugFormat(msg, args);
}
// Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args)
{
m_scene.PhysicsLogging.Write(msg, args);
}
}
}

View File

@ -42,6 +42,8 @@ public sealed class BSPrim : PhysicsActor
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS PRIM]";
private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); }
private IMesh _mesh;
private PrimitiveBaseShape _pbs;
private ShapeData.PhysicsShapeType _shapeType;
@ -50,6 +52,7 @@ public sealed class BSPrim : PhysicsActor
private List<ConvexResult> _hulls;
private BSScene _scene;
public BSScene Scene { get { return _scene; } }
private String _avName;
private uint _localID = 0;
@ -63,7 +66,7 @@ public sealed class BSPrim : PhysicsActor
private bool _isSelected;
private bool _isVolumeDetect;
private OMV.Vector3 _position;
private float _mass;
private float _mass; // the mass of this object
private float _density;
private OMV.Vector3 _force;
private OMV.Vector3 _velocity;
@ -86,14 +89,25 @@ public sealed class BSPrim : PhysicsActor
private bool _kinematic;
private float _buoyancy;
private List<BSPrim> _childrenPrims;
private BSPrim _parentPrim;
// Membership in a linkset is controlled by this class.
private BSLinkset _linkset;
public BSLinkset Linkset
{
get { return _linkset; }
set { _linkset = value; }
}
private int _subscribedEventsMs = 0;
private int _nextCollisionOkTime = 0;
long _collidingStep;
long _collidingGroundStep;
private BulletBody m_body;
public BulletBody Body {
get { return m_body; }
set { m_body = value; }
}
private BSDynamics _vehicle;
private OMV.Vector3 _PIDTarget;
@ -127,17 +141,18 @@ public sealed class BSPrim : PhysicsActor
_friction = _scene.Params.defaultFriction; // TODO: compute based on object material
_density = _scene.Params.defaultDensity; // TODO: compute based on object material
_restitution = _scene.Params.defaultRestitution;
_parentPrim = null; // not a child or a parent
_linkset = new BSLinkset(_scene, this); // a linkset of one
_vehicle = new BSDynamics(this); // add vehicleness
_childrenPrims = new List<BSPrim>();
if (_isPhysical)
_mass = CalculateMass();
else
_mass = 0f;
_mass = CalculateMass();
// do the actual object creation at taint time
_scene.TaintedObject(delegate()
{
RecreateGeomAndObject();
// Get the pointer to the physical body for this object.
// At the moment, we're still letting BulletSim manage the creation and destruction
// of the object. Someday we'll move that into the C# code.
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
});
}
@ -145,13 +160,19 @@ public sealed class BSPrim : PhysicsActor
public void Destroy()
{
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
// DetailLog("{0},Destroy", LocalID);
// Undo any vehicle properties
_vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
_scene.RemoveVehiclePrim(this); // just to make sure
_scene.TaintedObject(delegate()
{
// Undo any links between me and any other object
_linkset = _linkset.RemoveMeFromLinkset(this);
// everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
});
}
@ -164,8 +185,9 @@ public sealed class BSPrim : PhysicsActor
_size = value;
_scene.TaintedObject(delegate()
{
if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical);
_mass = CalculateMass(); // changing size changes the mass
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
RecreateGeomAndObject();
});
}
@ -175,7 +197,7 @@ public sealed class BSPrim : PhysicsActor
_pbs = value;
_scene.TaintedObject(delegate()
{
if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass
_mass = CalculateMass(); // changing the shape changes the mass
RecreateGeomAndObject();
});
}
@ -202,33 +224,10 @@ public sealed class BSPrim : PhysicsActor
// link me to the specified parent
public override void link(PhysicsActor obj) {
BSPrim parent = obj as BSPrim;
// m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
// TODO: decide if this parent checking needs to happen at taint time
if (_parentPrim == null)
{
if (parent != null)
{
// I don't have a parent so I am joining a linkset
parent.AddChildToLinkset(this);
}
}
else
{
// I already have a parent, is parenting changing?
if (parent != _parentPrim)
{
if (parent == null)
{
// we are being removed from a linkset
_parentPrim.RemoveChildFromLinkset(this);
}
else
{
// asking to reparent a prim should not happen
m_log.ErrorFormat("{0}: Reparenting a prim. ", LogHeader);
}
}
}
DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
_linkset = _linkset.AddMeToLinkset(this, parent);
return;
}
@ -236,101 +235,92 @@ public sealed class BSPrim : PhysicsActor
public override void delink() {
// TODO: decide if this parent checking needs to happen at taint time
// Race condition here: if link() and delink() in same simulation tick, the delink will not happen
// m_log.DebugFormat("{0}: delink {1}/{2}", LogHeader, _avName, _localID);
if (_parentPrim != null)
{
_parentPrim.RemoveChildFromLinkset(this);
}
DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
_linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
_linkset.RemoveMeFromLinkset(this);
return;
}
// I am the root of a linkset and a new child is being added
public void AddChildToLinkset(BSPrim pchild)
{
BSPrim child = pchild;
_scene.TaintedObject(delegate()
{
if (!_childrenPrims.Contains(child))
{
_childrenPrims.Add(child);
child.ParentPrim = this; // the child has gained a parent
RecreateGeomAndObject(); // rebuild my shape with the new child added
}
});
return;
}
// I am the root of a linkset and one of my children is being removed.
// Safe to call even if the child is not really in my linkset.
public void RemoveChildFromLinkset(BSPrim pchild)
{
BSPrim child = pchild;
_scene.TaintedObject(delegate()
{
if (_childrenPrims.Contains(child))
{
BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID);
_childrenPrims.Remove(child);
child.ParentPrim = null; // the child has lost its parent
RecreateGeomAndObject(); // rebuild my shape with the child removed
}
else
{
m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset");
}
});
return;
}
public BSPrim ParentPrim
{
set { _parentPrim = value; }
}
// return true if we are the root of a linkset (there are children to manage)
public bool IsRootOfLinkset
{
get { return (_parentPrim == null && _childrenPrims.Count != 0); }
}
// Set motion values to zero.
// Do it to the properties so the values get set in the physics engine.
// Push the setting of the values to the viewer.
private void ZeroMotion()
// Called at taint time!
public void ZeroMotion()
{
Velocity = OMV.Vector3.Zero;
_velocity = OMV.Vector3.Zero;
_acceleration = OMV.Vector3.Zero;
RotationalVelocity = OMV.Vector3.Zero;
base.RequestPhysicsterseUpdate();
_rotationalVelocity = OMV.Vector3.Zero;
// Zero some other properties directly into the physics engine
BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
BulletSimAPI.ClearForces2(Body.Ptr);
}
public override void LockAngularMotion(OMV.Vector3 axis) { return; }
public override void LockAngularMotion(OMV.Vector3 axis)
{
DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis);
return;
}
public override OMV.Vector3 Position {
get {
// don't do the following GetObjectPosition because this function is called a zillion times
if (!_linkset.IsRoot(this))
// child prims move around based on their parent. Need to get the latest location
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
// don't do the GetObjectPosition for root elements because this function is called a zillion times
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
return _position;
}
set {
_position = value;
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
_scene.TaintedObject(delegate()
{
DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
// m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position);
});
}
}
public override float Mass {
get { return _mass; }
// Return the effective mass of the object.
// If there are multiple items in the linkset, add them together for the root
public override float Mass
{
get
{
return _linkset.LinksetMass;
}
}
// used when we only want this prim's mass and not the linkset thing
public float MassRaw { get { return _mass; } }
// Is this used?
public override OMV.Vector3 CenterOfMass
{
get { return _linkset.CenterOfMass; }
}
// Is this used?
public override OMV.Vector3 GeometricCenter
{
get { return _linkset.GeometricCenter; }
}
public override OMV.Vector3 Force {
get { return _force; }
set {
_force = value;
_scene.TaintedObject(delegate()
{
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
// BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
});
}
}
@ -341,15 +331,22 @@ public sealed class BSPrim : PhysicsActor
}
set {
Vehicle type = (Vehicle)value;
_vehicle.ProcessTypeChange(type);
_scene.TaintedObject(delegate()
{
DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type);
_vehicle.ProcessTypeChange(type);
if (type == Vehicle.TYPE_NONE)
{
_scene.RemoveVehiclePrim(this);
}
else
{
_scene.TaintedObject(delegate()
{
// Tell the physics engine to clear state
BulletSimAPI.ClearForces2(this.Body.Ptr);
});
// make it so the scene will call us each tick to do vehicle things
_scene.AddVehiclePrim(this);
}
@ -359,47 +356,59 @@ public sealed class BSPrim : PhysicsActor
}
public override void VehicleFloatParam(int param, float value)
{
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
_scene.TaintedObject(delegate()
{
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
});
}
public override void VehicleVectorParam(int param, OMV.Vector3 value)
{
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
_scene.TaintedObject(delegate()
{
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
});
}
public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
{
_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
_scene.TaintedObject(delegate()
{
_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
});
}
public override void VehicleFlags(int param, bool remove)
{
_vehicle.ProcessVehicleFlags(param, remove);
_scene.TaintedObject(delegate()
{
_vehicle.ProcessVehicleFlags(param, remove);
});
}
// Called each simulation step to advance vehicle characteristics
// Called each simulation step to advance vehicle characteristics.
// Called from Scene when doing simulation step so we're in taint processing time.
public void StepVehicle(float timeStep)
{
_vehicle.Step(timeStep, _scene);
if (IsPhysical)
_vehicle.Step(timeStep);
}
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
public override void SetVolumeDetect(int param) {
bool newValue = (param != 0);
if (_isVolumeDetect != newValue)
_isVolumeDetect = newValue;
_scene.TaintedObject(delegate()
{
_isVolumeDetect = newValue;
_scene.TaintedObject(delegate()
{
SetObjectDynamic();
});
}
SetObjectDynamic();
});
return;
}
public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
public override OMV.Vector3 Velocity {
get { return _velocity; }
set { _velocity = value;
set {
_velocity = value;
_scene.TaintedObject(delegate()
{
DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity);
BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
});
}
@ -407,6 +416,7 @@ public sealed class BSPrim : PhysicsActor
public override OMV.Vector3 Torque {
get { return _torque; }
set { _torque = value;
DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque);
}
}
public override float CollisionScore {
@ -419,13 +429,21 @@ public sealed class BSPrim : PhysicsActor
set { _acceleration = value; }
}
public override OMV.Quaternion Orientation {
get { return _orientation; }
get {
if (!_linkset.IsRoot(this))
{
// Children move around because tied to parent. Get a fresh value.
_orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
}
return _orientation;
}
set {
_orientation = value;
// m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation);
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
_scene.TaintedObject(delegate()
{
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
});
}
@ -458,25 +476,24 @@ public sealed class BSPrim : PhysicsActor
get { return !IsPhantom && !_isVolumeDetect; }
}
// make gravity work if the object is physical and not selected
// no locking here because only called when it is safe
// Make gravity work if the object is physical and not selected
// No locking here because only called when it is safe
// Only called at taint time so it is save to call into Bullet.
private void SetObjectDynamic()
{
// m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid);
// non-physical things work best with a mass of zero
if (IsStatic)
{
_mass = 0f;
}
else
{
_mass = CalculateMass();
// If it's dynamic, make sure the hull has been created for it
// This shouldn't do much work if the object had previously been built
RecreateGeomAndObject();
// RA: remove this for the moment.
// The problem is that dynamic objects are hulls so if we are becoming physical
// the shape has to be checked and possibly built.
// Maybe a VerifyCorrectPhysicalShape() routine?
// RecreateGeomAndObject();
}
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass);
float mass = _mass;
// Bullet wants static objects have a mass of zero
if (IsStatic)
mass = 0f;
DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
}
// prims don't fly
@ -516,11 +533,24 @@ public sealed class BSPrim : PhysicsActor
set { _floatOnWater = value; }
}
public override OMV.Vector3 RotationalVelocity {
get { return _rotationalVelocity; }
set { _rotationalVelocity = value;
get {
/*
OMV.Vector3 pv = OMV.Vector3.Zero;
// if close to zero, report zero
// This is copied from ODE but I'm not sure why it returns zero but doesn't
// zero the property in the physics engine.
if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
return pv;
*/
return _rotationalVelocity;
}
set {
_rotationalVelocity = value;
// m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
_scene.TaintedObject(delegate()
{
DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
});
}
@ -533,11 +563,13 @@ public sealed class BSPrim : PhysicsActor
}
public override float Buoyancy {
get { return _buoyancy; }
set { _buoyancy = value;
_scene.TaintedObject(delegate()
{
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
});
set {
_buoyancy = value;
_scene.TaintedObject(delegate()
{
DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
});
}
}
@ -573,27 +605,45 @@ public sealed class BSPrim : PhysicsActor
public override float APIDStrength { set { return; } }
public override float APIDDamping { set { return; } }
private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
public override void AddForce(OMV.Vector3 force, bool pushforce) {
if (force.IsFinite())
{
_force.X += force.X;
_force.Y += force.Y;
_force.Z += force.Z;
// _force += force;
lock (m_accumulatedForces)
m_accumulatedForces.Add(new OMV.Vector3(force));
}
else
{
m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
return;
}
_scene.TaintedObject(delegate()
{
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
lock (m_accumulatedForces)
{
if (m_accumulatedForces.Count > 0)
{
OMV.Vector3 fSum = OMV.Vector3.Zero;
foreach (OMV.Vector3 v in m_accumulatedForces)
{
fSum += v;
}
m_accumulatedForces.Clear();
DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
}
}
});
}
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
// m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
}
public override void SetMomentum(OMV.Vector3 momentum) {
DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum);
}
public override void SubscribeEvents(int ms) {
_subscribedEventsMs = ms;
@ -885,6 +935,9 @@ public sealed class BSPrim : PhysicsActor
returnMass = _density * volume;
/*
* This change means each object keeps its own mass and the Mass property
* will return the sum if we're part of a linkset.
if (IsRootOfLinkset)
{
foreach (BSPrim prim in _childrenPrims)
@ -892,6 +945,7 @@ public sealed class BSPrim : PhysicsActor
returnMass += prim.CalculateMass();
}
}
*/
if (returnMass <= 0)
returnMass = 0.0001f;
@ -907,9 +961,11 @@ public sealed class BSPrim : PhysicsActor
// The objects needs a hull if it's physical otherwise a mesh is enough
// No locking here because this is done when we know physics is not simulating
// if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
private void CreateGeom(bool forceRebuild)
// Returns 'true' if the geometry was rebuilt
private bool CreateGeom(bool forceRebuild)
{
// the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
bool ret = false;
if (!_scene.NeedsMeshing(_pbs))
{
if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@ -917,16 +973,28 @@ public sealed class BSPrim : PhysicsActor
if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
{
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
// Bullet native objects are scaled by the Bullet engine so pass the size in
_scale = _size;
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
{
DetailLog("{0},CreateGeom,sphere", LocalID);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
// Bullet native objects are scaled by the Bullet engine so pass the size in
_scale = _size;
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
ret = true;
}
}
}
else
{
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
_scale = _size;
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
{
DetailLog("{0},CreateGeom,box", LocalID);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
_scale = _size;
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
ret = true;
}
}
}
else
@ -938,6 +1006,7 @@ public sealed class BSPrim : PhysicsActor
// physical objects require a hull for interaction.
// This will create the mesh if it doesn't already exist
CreateGeomHull();
ret = true;
}
}
else
@ -946,9 +1015,11 @@ public sealed class BSPrim : PhysicsActor
{
// Static (non-physical) objects only need a mesh for bumping into
CreateGeomMesh();
ret = true;
}
}
}
return ret;
}
// No locking here because this is done when we know physics is not simulating
@ -961,10 +1032,12 @@ public sealed class BSPrim : PhysicsActor
// if this new shape is the same as last time, don't recreate the mesh
if (_meshKey == newMeshKey) return;
DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey);
// Since we're recreating new, get rid of any previously generated shape
if (_meshKey != 0)
{
// m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
_mesh = null;
_meshKey = 0;
@ -981,7 +1054,6 @@ public sealed class BSPrim : PhysicsActor
int vi = 0;
foreach (OMV.Vector3 vv in vertices)
{
// m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z);
verticesAsFloats[vi++] = vv.X;
verticesAsFloats[vi++] = vv.Y;
verticesAsFloats[vi++] = vv.Z;
@ -995,6 +1067,7 @@ public sealed class BSPrim : PhysicsActor
_shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
// meshes are already scaled by the meshmerizer
_scale = new OMV.Vector3(1f, 1f, 1f);
DetailLog("{0},CreateGeomMesh,done", LocalID);
return;
}
@ -1008,13 +1081,17 @@ public sealed class BSPrim : PhysicsActor
// if the hull hasn't changed, don't rebuild it
if (newHullKey == _hullKey) return;
DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey);
// Since we're recreating new, get rid of any previously generated shape
if (_hullKey != 0)
{
// m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
_hullKey = 0;
_hulls.Clear();
DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
_mesh = null; // the mesh cannot match either
_meshKey = 0;
@ -1111,6 +1188,7 @@ public sealed class BSPrim : PhysicsActor
_shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
// meshes are already scaled by the meshmerizer
_scale = new OMV.Vector3(1f, 1f, 1f);
DetailLog("{0},CreateGeomHull,done", LocalID);
return;
}
@ -1124,47 +1202,21 @@ public sealed class BSPrim : PhysicsActor
// Create an object in Bullet if it has not already been created
// No locking here because this is done when the physics engine is not simulating
private void CreateObject()
// Returns 'true' if an object was actually created.
private bool CreateObject()
{
if (IsRootOfLinkset)
{
// Create a linkset around this object
// CreateLinksetWithCompoundHull();
CreateLinksetWithConstraints();
}
else
{
// simple object
// the mesh or hull must have already been created in Bullet
ShapeData shape;
FillShapeInfo(out shape);
// m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
BulletSimAPI.CreateObject(_scene.WorldID, shape);
}
}
// this routine is called when objects are rebuilt.
// Create a linkset by creating a compound hull at the root prim that consists of all
// the children.
// NOTE: This does not allow proper collisions with the children prims so it is not a workable solution
void CreateLinksetWithCompoundHull()
{
// If I am the root prim of a linkset, replace my physical shape with all the
// pieces of the children.
// All of the children should have called CreateGeom so they have a hull
// in the physics engine already. Here we pull together all of those hulls
// into one shape.
int totalPrimsInLinkset = _childrenPrims.Count + 1;
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset);
ShapeData[] shapes = new ShapeData[totalPrimsInLinkset];
FillShapeInfo(out shapes[0]);
int ii = 1;
foreach (BSPrim prim in _childrenPrims)
{
// m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID);
prim.FillShapeInfo(out shapes[ii]);
ii++;
}
BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
// the mesh or hull must have already been created in Bullet
ShapeData shape;
FillShapeInfo(out shape);
// m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
// the CreateObject() may have recreated the rigid body. Make sure we have the latest.
m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
return ret;
}
// Copy prim's info into the BulletSim shape description structure
@ -1186,44 +1238,6 @@ public sealed class BSPrim : PhysicsActor
shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
}
// Create the linkset by putting constraints between the objects of the set so they cannot move
// relative to each other.
// TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added
void CreateLinksetWithConstraints()
{
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
// remove any constraints that might be in place
foreach (BSPrim prim in _childrenPrims)
{
// m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
}
// create constraints between the root prim and each of the children
foreach (BSPrim prim in _childrenPrims)
{
// m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
// Zero motion for children so they don't interpolate
prim.ZeroMotion();
// relative position normalized to the root prim
OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation);
// relative rotation of the child to the parent
OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation;
// this is a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
childRelativePosition,
relativeRotation,
OMV.Vector3.Zero,
OMV.Quaternion.Identity,
OMV.Vector3.Zero, OMV.Vector3.Zero,
OMV.Vector3.Zero, OMV.Vector3.Zero);
}
}
// Rebuild the geometry and object.
// This is called when the shape changes so we need to recreate the mesh/hull.
@ -1231,8 +1245,8 @@ public sealed class BSPrim : PhysicsActor
private void RecreateGeomAndObject()
{
// m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID);
CreateGeom(true);
CreateObject();
if (CreateGeom(true))
CreateObject();
return;
}
@ -1252,77 +1266,77 @@ public sealed class BSPrim : PhysicsActor
const float POSITION_TOLERANCE = 0.05f;
const float ACCELERATION_TOLERANCE = 0.01f;
const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
const bool SHOULD_DAMP_UPDATES = false;
public void UpdateProperties(EntityProperties entprop)
{
/*
UpdatedProperties changed = 0;
if (SHOULD_DAMP_UPDATES)
// assign to the local variables so the normal set action does not happen
// if (_position != entprop.Position)
if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
{
// assign to the local variables so the normal set action does not happen
// if (_position != entprop.Position)
if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
_position = entprop.Position;
changed |= UpdatedProperties.Position;
}
// if (_orientation != entprop.Rotation)
if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
{
_orientation = entprop.Rotation;
changed |= UpdatedProperties.Rotation;
}
// if (_velocity != entprop.Velocity)
if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
{
_velocity = entprop.Velocity;
changed |= UpdatedProperties.Velocity;
}
// if (_acceleration != entprop.Acceleration)
if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
{
_acceleration = entprop.Acceleration;
changed |= UpdatedProperties.Acceleration;
}
// if (_rotationalVelocity != entprop.RotationalVelocity)
if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
{
_rotationalVelocity = entprop.RotationalVelocity;
changed |= UpdatedProperties.RotationalVel;
}
if (changed != 0)
{
// Only update the position of single objects and linkset roots
if (this._parentPrim == null)
{
_position = entprop.Position;
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position);
changed |= UpdatedProperties.Position;
}
// if (_orientation != entprop.Rotation)
if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
{
_orientation = entprop.Rotation;
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation);
changed |= UpdatedProperties.Rotation;
}
// if (_velocity != entprop.Velocity)
if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
{
_velocity = entprop.Velocity;
// m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
changed |= UpdatedProperties.Velocity;
}
// if (_acceleration != entprop.Acceleration)
if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
{
_acceleration = entprop.Acceleration;
// m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
changed |= UpdatedProperties.Acceleration;
}
// if (_rotationalVelocity != entprop.RotationalVelocity)
if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
{
_rotationalVelocity = entprop.RotationalVelocity;
// m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
changed |= UpdatedProperties.RotationalVel;
}
if (changed != 0)
{
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
// Only update the position of single objects and linkset roots
if (this._parentPrim == null)
{
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
base.RequestPhysicsterseUpdate();
}
base.RequestPhysicsterseUpdate();
}
}
*/
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
// Updates only for individual prims and for the root object of a linkset.
if (_linkset.IsRoot(this))
{
// Assign to the local variables so the normal set action does not happen
_position = entprop.Position;
_orientation = entprop.Rotation;
_velocity = entprop.Velocity;
_acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity;
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
// LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
base.RequestPhysicsterseUpdate();
}
else
{
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
// Only updates only for individual prims and for the root object of a linkset.
if (this._parentPrim == null)
{
// Assign to the local variables so the normal set action does not happen
_position = entprop.Position;
_orientation = entprop.Rotation;
_velocity = entprop.Velocity;
_acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity;
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
// LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
base.RequestPhysicsterseUpdate();
}
// For debugging, we can also report the movement of children
DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
entprop.Acceleration, entprop.RotationalVelocity);
}
}
@ -1362,5 +1376,11 @@ public sealed class BSPrim : PhysicsActor
collisionCollection.Clear();
}
}
// Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args)
{
Scene.PhysicsLogging.Write(msg, args);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,28 @@ using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin {
// Classes to allow some type checking for the API
public struct BulletSim
{
public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; }
public IntPtr Ptr;
public uint ID;
}
public struct BulletBody
{
public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
public IntPtr Ptr;
public uint ID;
}
public struct BulletConstraint
{
public BulletConstraint(IntPtr xx) { Ptr = xx; }
public IntPtr Ptr;
}
// ===============================================================================
[StructLayout(LayoutKind.Sequential)]
public struct ConvexHull
{
@ -44,13 +66,14 @@ public struct ShapeData
{
public enum PhysicsShapeType
{
SHAPE_AVATAR = 0,
SHAPE_BOX = 1,
SHAPE_CONE = 2,
SHAPE_CYLINDER = 3,
SHAPE_SPHERE = 4,
SHAPE_MESH = 5,
SHAPE_HULL = 6
SHAPE_UNKNOWN = 0,
SHAPE_AVATAR = 1,
SHAPE_BOX = 2,
SHAPE_CONE = 3,
SHAPE_CYLINDER = 4,
SHAPE_SPHERE = 5,
SHAPE_MESH = 6,
SHAPE_HULL = 7
};
public uint ID;
public PhysicsShapeType Type;
@ -64,12 +87,12 @@ public struct ShapeData
public System.UInt64 MeshKey;
public float Friction;
public float Restitution;
public int Collidable;
public int Static; // true if a static object. Otherwise gravity, etc.
public float Collidable; // true of things bump into this
public float Static; // true if a static object. Otherwise gravity, etc.
// note that bools are passed as ints since bool size changes by language and architecture
public const int numericTrue = 1;
public const int numericFalse = 0;
// note that bools are passed as floats since bool size changes by language and architecture
public const float numericTrue = 1f;
public const float numericFalse = 0f;
}
[StructLayout(LayoutKind.Sequential)]
public struct SweepHit
@ -142,10 +165,56 @@ public struct ConfigurationParameters
public float shouldEnableFrictionCaching;
public float numberOfSolverIterations;
public float linkConstraintUseFrameOffset;
public float linkConstraintEnableTransMotor;
public float linkConstraintTransMotorMaxVel;
public float linkConstraintTransMotorMaxForce;
public float linkConstraintERP;
public float linkConstraintCFM;
public const float numericTrue = 1f;
public const float numericFalse = 0f;
}
// Values used by Bullet and BulletSim to control collisions
public enum CollisionFlags : uint
{
STATIC_OBJECT = 1 << 0,
KINEMATIC_OBJECT = 1 << 1,
NO_CONTACT_RESPONSE = 1 << 2,
CUSTOM_MATERIAL_CALLBACK = 1 << 3,
CHARACTER_OBJECT = 1 << 4,
DISABLE_VISUALIZE_OBJECT = 1 << 5,
DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
// Following used by BulletSim to control collisions
VOLUME_DETECT_OBJECT = 1 << 10,
PHANTOM_OBJECT = 1 << 11,
PHYSICAL_OBJECT = 1 << 12,
};
// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
public enum ConstraintParams : int
{
BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730
BT_CONSTRAINT_STOP_ERP,
BT_CONSTRAINT_CFM,
BT_CONSTRAINT_STOP_CFM,
};
public enum ConstraintParamAxis : int
{
AXIS_LINEAR_X = 0,
AXIS_LINEAR_Y,
AXIS_LINEAR_Z,
AXIS_ANGULAR_X,
AXIS_ANGULAR_Y,
AXIS_ANGULAR_Z,
AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls
AXIS_ANGULAR_ALL,
AXIS_ALL
};
// ===============================================================================
static class BulletSimAPI {
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@ -195,6 +264,7 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool CreateObject(uint worldID, ShapeData shapeData);
/* Remove old functionality
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
@ -209,10 +279,14 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
*/
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Quaternion GetObjectOrientation(uint WorldID, uint id);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation);
@ -268,5 +342,179 @@ public static extern void DumpBulletStatistics();
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetDebugLogCallback(DebugLogCallback callback);
// ===============================================================================
// ===============================================================================
// ===============================================================================
// A new version of the API that enables moving all the logic out of the C++ code and into
// the C# code. This will make modifications easier for the next person.
// This interface passes the actual pointers to the objects in the unmanaged
// address space. All the management (calls for creation/destruction/lookup)
// is done in the C# code.
// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
// and the old code is removed.
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr GetSimHandle2(uint worldID);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id);
// ===============================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
int maxCollisions, IntPtr collisionArray,
int maxUpdates, IntPtr updateArray);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetHeightmap2(IntPtr sim, float[] heightmap);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void Shutdown2(IntPtr sim);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount,
out IntPtr updatedEntitiesPtr,
out int collidersCount,
out IntPtr collidersPtr);
/*
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices );
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool BuildHull2(IntPtr sim, IntPtr mesh);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData);
*/
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2,
Vector3 frame1loc, Quaternion frame1rot,
Vector3 frame2loc, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool CalculateTransforms2(IntPtr constrain);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetPosition2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Quaternion GetOrientation2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetDeactivationTime2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetFriction2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetRestitution2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateInertiaTensor2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetGravity2(IntPtr obj, Vector3 val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr ClearForces2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetMargin2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyObject2(IntPtr world, uint id);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void DumpPhysicsStatistics2(IntPtr sim);
}
}

View File

@ -71,6 +71,9 @@ namespace OpenSim.Region.Physics.Manager
All = 0x3f
}
public delegate void RequestAssetDelegate(UUID assetID, AssetReceivedDelegate callback);
public delegate void AssetReceivedDelegate(AssetBase asset);
/// <summary>
/// Contact result from a raycast.
/// </summary>
@ -103,6 +106,8 @@ namespace OpenSim.Region.Physics.Manager
get { return new NullPhysicsScene(); }
}
public RequestAssetDelegate RequestAssetMethod { private get; set; }
public virtual void TriggerPhysicsBasedRestart()
{
physicsCrash handler = OnPhysicsCrash;

View File

@ -290,7 +290,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private readonly IntPtr contactgroup;
internal IntPtr LandGeom;
internal IntPtr WaterGeom;
private float nmTerrainContactFriction = 255.0f;
@ -489,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
/// </summary>
internal Object OdeLock = new Object();
private bool _worldInitialized = false;
public IMesher mesher;
private IConfigSource m_config;
@ -875,6 +876,8 @@ namespace OpenSim.Region.Physics.OdePlugin
staticPrimspace[i, j] = IntPtr.Zero;
}
}
_worldInitialized = true;
}
// internal void waitForSpaceUnlock(IntPtr space)
@ -1508,8 +1511,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f)
&& (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f)
&& (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))
&& contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
&& (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
{
if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
{
@ -1538,7 +1540,7 @@ namespace OpenSim.Region.Physics.OdePlugin
//d.GeomGetAABB(contactGeom.g2, out aabb2);
//d.GeomGetAABB(contactGeom.g1, out aabb1);
//aabb1.
if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
{
if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
{
@ -2896,6 +2898,8 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <returns>The number of frames simulated over that period.</returns>
public override float Simulate(float timeStep)
{
if (!_worldInitialized) return 11f;
int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
int tempTick = 0, tempTick2 = 0;
@ -4017,6 +4021,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public override void Dispose()
{
_worldInitialized = false;
m_rayCastManager.Dispose();
m_rayCastManager = null;
@ -4037,6 +4043,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.WorldDestroy(world);
//d.CloseODE();
}
}
public override Dictionary<uint, float> GetTopColliders()

View File

@ -99,6 +99,8 @@ namespace OpenSim.Region.RegionCombinerModule
public void RemoveRegion(Scene scene)
{
lock (m_startingScenes)
m_startingScenes.Remove(scene.RegionInfo.originRegionID);
}
public void RegionLoaded(Scene scene)

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared;

View File

@ -6885,22 +6885,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (folderID == UUID.Zero)
return;
byte[] bucket = new byte[1];
bucket[0] = (byte)AssetType.Folder;
//byte[] objBytes = folderID.GetBytes();
//Array.Copy(objBytes, 0, bucket, 1, 16);
GridInstantMessage msg = new GridInstantMessage(World,
m_host.OwnerID, m_host.Name, destID,
(byte)InstantMessageDialog.TaskInventoryOffered,
false, category+". "+m_host.Name+" is located at "+
World.RegionInfo.RegionName+" "+
m_host.AbsolutePosition.ToString(),
folderID, true, m_host.AbsolutePosition,
bucket);
if (m_TransferModule != null)
{
byte[] bucket = new byte[] { (byte)AssetType.Folder };
GridInstantMessage msg = new GridInstantMessage(World,
m_host.UUID, m_host.Name + ", an object owned by " +
resolveName(m_host.OwnerID) + ",", destID,
(byte)InstantMessageDialog.TaskInventoryOffered,
false, category + "\n" + m_host.Name + " is located at " +
World.RegionInfo.RegionName + " " +
m_host.AbsolutePosition.ToString(),
folderID, true, m_host.AbsolutePosition,
bucket);
m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
}
}
public void llSetVehicleType(int type)
@ -11847,7 +11847,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break;
case ScriptBaseClass.OBJECT_ROT:
{
Quaternion rot = Quaternion.Identity;
Quaternion rot = Quaternion.Identity;
if (obj.ParentGroup.RootPart == obj)
rot = obj.ParentGroup.GroupRotation;

View File

@ -200,24 +200,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
for (int i = 0; i < result.Length; i++)
{
if (result[i] is string)
{
llist[i] = new LSL_String((string)result[i]);
}
else if (result[i] is int)
{
llist[i] = new LSL_Integer((int)result[i]);
}
else if (result[i] is float)
{
llist[i] = new LSL_Float((float)result[i]);
}
else if (result[i] is UUID)
{
llist[i] = new LSL_Key(result[i].ToString());
}
else if (result[i] is OpenMetaverse.Vector3)
{
OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i];
llist[i] = new LSL_Vector(vresult.X,vresult.Y,vresult.Z);
llist[i] = new LSL_Vector(vresult.X, vresult.Y, vresult.Z);
}
else if (result[i] is OpenMetaverse.Quaternion)
{
OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i];
llist[i] = new LSL_Rotation(qresult.X,qresult.Y,qresult.Z,qresult.W);
llist[i] = new LSL_Rotation(qresult.X, qresult.Y, qresult.Z, qresult.W);
}
else
{
MODError(String.Format("unknown list element returned by {0}",fname));
MODError(String.Format("unknown list element {1} returned by {0}", fname, result[i].GetType().Name));
}
}

View File

@ -3290,8 +3290,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName));
throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName));
return;
}
ScenePresence sp = World.GetScenePresence(avatarId);
@ -3322,5 +3320,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
InitLSL();
((LSL_Api)m_LSL_Api).DetachFromAvatar();
}
/// <summary>
/// Checks if thing is a UUID.
/// </summary>
/// <param name="thing"></param>
/// <returns>1 if thing is a valid UUID, 0 otherwise</returns>
public LSL_Integer osIsUUID(string thing)
{
CheckThreatLevel(ThreatLevel.None, "osIsUUID");
m_host.AddScriptLPS(1);
UUID test;
return UUID.TryParse(thing, out test) ? 1 : 0;
}
/// <summary>
/// Wraps to Math.Min()
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public LSL_Float osMin(double a, double b)
{
CheckThreatLevel(ThreatLevel.None, "osMin");
m_host.AddScriptLPS(1);
return Math.Min(a, b);
}
/// <summary>
/// Wraps to Math.max()
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public LSL_Float osMax(double a, double b)
{
CheckThreatLevel(ThreatLevel.None, "osMax");
m_host.AddScriptLPS(1);
return Math.Max(a, b);
}
}
}

View File

@ -51,8 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
{
get
{
lock (SenseRepeatListLock)
return SenseRepeaters.Count;
return SenseRepeaters.Count;
}
}
@ -61,8 +60,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
m_CmdManager = CmdManager;
maximumRange = CmdManager.m_ScriptEngine.Config.GetDouble("SensorMaxRange", 96.0d);
maximumToReturn = CmdManager.m_ScriptEngine.Config.GetInt("SensorMaxResults", 16);
m_npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<INPCModule>();
}
private INPCModule m_npcModule;
private Object SenseLock = new Object();
private const int AGENT = 1;
@ -115,6 +117,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
public double distance;
}
/// <summary>
/// Sensors to process.
/// </summary>
/// <remarks>
/// Do not add or remove sensors from this list directly. Instead, copy the list and substitute the updated
/// copy. This is to avoid locking the list for the duration of the sensor sweep, which increases the danger
/// of deadlocks with future code updates.
///
/// Always lock SenseRepeatListLock when updating this list.
/// </remarks>
private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
private object SenseRepeatListLock = new object();
@ -124,6 +136,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
{
// Always remove first, in case this is a re-set
UnSetSenseRepeaterEvents(m_localID, m_itemID);
if (sec == 0) // Disabling timer
return;
@ -143,9 +156,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
ts.host = host;
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
AddSenseRepeater(ts);
}
private void AddSenseRepeater(SenseRepeatClass senseRepeater)
{
lock (SenseRepeatListLock)
{
SenseRepeaters.Add(ts);
List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(SenseRepeaters);
newSenseRepeaters.Add(senseRepeater);
SenseRepeaters = newSenseRepeaters;
}
}
@ -154,39 +175,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
// Remove from timer
lock (SenseRepeatListLock)
{
List<SenseRepeatClass> NewSensors = new List<SenseRepeatClass>();
List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>();
foreach (SenseRepeatClass ts in SenseRepeaters)
{
if (ts.localID != m_localID || ts.itemID != m_itemID)
{
NewSensors.Add(ts);
newSenseRepeaters.Add(ts);
}
}
SenseRepeaters.Clear();
SenseRepeaters = NewSensors;
SenseRepeaters = newSenseRepeaters;
}
}
public void CheckSenseRepeaterEvents()
{
lock (SenseRepeatListLock)
// Go through all timers
foreach (SenseRepeatClass ts in SenseRepeaters)
{
// Nothing to do here?
if (SenseRepeaters.Count == 0)
return;
// Go through all timers
foreach (SenseRepeatClass ts in SenseRepeaters)
// Time has passed?
if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
{
// Time has passed?
if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
{
SensorSweep(ts);
// set next interval
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
}
SensorSweep(ts);
// set next interval
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
}
} // lock
}
}
public void SenseOnce(uint m_localID, UUID m_itemID,
@ -440,8 +454,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
private List<SensedEntity> doAgentSensor(SenseRepeatClass ts)
{
INPCModule npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<INPCModule>();
List<SensedEntity> sensedEntities = new List<SensedEntity>();
// If nobody about quit fast
@ -477,7 +489,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
Vector3 toRegionPos;
double dis;
Action<ScenePresence> senseEntity = new Action<ScenePresence>(presence =>
{
// m_log.DebugFormat(
@ -486,7 +498,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
if ((ts.type & NPC) == 0 && presence.PresenceType == PresenceType.Npc)
{
INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene);
INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene);
if (npcData == null || !npcData.SenseAsAgent)
{
// m_log.DebugFormat(
@ -504,7 +516,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
}
else
{
INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene);
INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene);
if (npcData != null && npcData.SenseAsAgent)
{
// m_log.DebugFormat(
@ -619,21 +631,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
{
List<Object> data = new List<Object>();
lock (SenseRepeatListLock)
foreach (SenseRepeatClass ts in SenseRepeaters)
{
foreach (SenseRepeatClass ts in SenseRepeaters)
if (ts.itemID == itemID)
{
if (ts.itemID == itemID)
{
data.Add(ts.interval);
data.Add(ts.name);
data.Add(ts.keyID);
data.Add(ts.type);
data.Add(ts.range);
data.Add(ts.arc);
}
data.Add(ts.interval);
data.Add(ts.name);
data.Add(ts.keyID);
data.Add(ts.type);
data.Add(ts.range);
data.Add(ts.arc);
}
}
return data.ToArray();
}
@ -667,8 +677,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
ts.next =
DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
lock (SenseRepeatListLock)
SenseRepeaters.Add(ts);
AddSenseRepeater(ts);
idx += 6;
}

View File

@ -276,5 +276,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
void osSetTerrainTexture(int level, LSL_Key texture);
void osSetTerrainTextureHeight(int corner, double low, double high);
/// <summary>
/// Checks if thing is a UUID.
/// </summary>
/// <param name="thing"></param>
/// <returns>1 if thing is a valid UUID, 0 otherwise</returns>
LSL_Integer osIsUUID(string thing);
/// <summary>
/// Wraps to Math.Min()
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
LSL_Float osMin(double a, double b);
/// <summary>
/// Wraps to Math.max()
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
LSL_Float osMax(double a, double b);
}
}

View File

@ -930,5 +930,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high);
}
public LSL_Integer osIsUUID(string thing)
{
return m_OSSL_Functions.osIsUUID(thing);
}
public LSL_Float osMin(double a, double b)
{
return m_OSSL_Functions.osMin(a, b);
}
public LSL_Float osMax(double a, double b)
{
return m_OSSL_Functions.osMax(a, b);
}
}
}

View File

@ -38,7 +38,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{
public class CSCodeGenerator : ICodeConverter
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private SYMBOL m_astRoot = null;
private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
@ -255,7 +255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
else if (s is IdentDotExpression)
retstr += Generate(CheckName(((IdentDotExpression) s).Name) + "." + ((IdentDotExpression) s).Member, s);
else if (s is IdentExpression)
retstr += Generate(CheckName(((IdentExpression) s).Name), s);
retstr += GenerateIdentifier(((IdentExpression) s).Name, s);
else if (s is IDENT)
retstr += Generate(CheckName(((TOKEN) s).yytext), s);
else
@ -867,6 +867,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
return retstr;
}
/// <summary>
/// Generates the code for an identifier
/// </summary>
/// <param name="id">The symbol name</param>
/// <param name="s">The Symbol node.</param>
/// <returns>String containing C# code for identifier reference.</returns>
private string GenerateIdentifier(string id, SYMBOL s)
{
if (m_comms != null)
{
object value = m_comms.LookupModConstant(id);
if (value != null)
{
string retval = null;
if (value is int)
retval = ((int)value).ToString();
else if (value is float)
retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString());
else if (value is string)
retval = String.Format("new LSL_Types.LSLString(\"{0}\")",((string)value));
else if (value is OpenMetaverse.UUID)
retval = String.Format("new LSL_Types.key(\"{0}\")",((OpenMetaverse.UUID)value).ToString());
else if (value is OpenMetaverse.Vector3)
retval = String.Format("new LSL_Types.Vector3(\"{0}\")",((OpenMetaverse.Vector3)value).ToString());
else if (value is OpenMetaverse.Quaternion)
retval = String.Format("new LSL_Types.Quaternion(\"{0}\")",((OpenMetaverse.Quaternion)value).ToString());
else retval = id;
return Generate(retval, s);
}
}
return Generate(CheckName(id), s);
}
/// <summary>
/// Generates the code for a FunctionCall node.
/// </summary>

View File

@ -36,6 +36,7 @@ using OpenSim.Framework;
using OpenSim.Region.CoreModules;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.ScriptEngine.Shared
{
@ -83,6 +84,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
public class DetectParams
{
public const int AGENT = 1;
public const int ACTIVE = 2;
public const int PASSIVE = 4;
public const int SCRIPTED = 8;
public const int OS_NPC = 0x01000000;
public DetectParams()
{
Key = UUID.Zero;
@ -199,8 +206,27 @@ namespace OpenSim.Region.ScriptEngine.Shared
Type = 0x01; // Avatar
if (presence.PresenceType == PresenceType.Npc)
Type = 0x20;
// Cope Impl. We don't use OS_NPC.
//if (presence.PresenceType != PresenceType.Npc)
//{
// Type = AGENT;
//}
//else
//{
// Type = OS_NPC;
// INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
// INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene);
// if (npcData.SenseAsAgent)
// {
// Type |= AGENT;
// }
//}
if (presence.Velocity != Vector3.Zero)
Type |= 0x02; // Active
Type |= ACTIVE;
Group = presence.ControllingClient.ActiveGroupId;
@ -215,15 +241,15 @@ namespace OpenSim.Region.ScriptEngine.Shared
Name = part.Name;
Owner = part.OwnerID;
if (part.Velocity == Vector3.Zero)
Type = 0x04; // Passive
Type = PASSIVE;
else
Type = 0x02; // Passive
Type = ACTIVE;
foreach (SceneObjectPart p in part.ParentGroup.Parts)
{
if (p.Inventory.ContainsScripts())
{
Type |= 0x08; // Scripted
Type |= SCRIPTED; // Scripted
break;
}
}

View File

@ -312,11 +312,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
part.SetScriptEvents(ItemID,
(int)m_Script.GetStateEventFlags(State));
Running = false;
if (ShuttingDown)
if (!Running)
m_startOnInit = false;
Running = false;
// we get new rez events on sim restart, too
// but if there is state, then we fire the change
// event
@ -352,12 +352,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
public void Init()
{
if (!m_startOnInit)
if (ShuttingDown)
return;
if (m_startedFromSavedState)
{
Start();
if (m_startOnInit)
Start();
if (m_postOnRez)
{
PostEvent(new EventParams("on_rez",
@ -389,7 +390,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
}
else
{
Start();
if (m_startOnInit)
Start();
PostEvent(new EventParams("state_entry",
new Object[0], new DetectParams[0]));
if (m_postOnRez)

View File

@ -109,6 +109,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private bool m_KillTimedOutScripts;
private string m_ScriptEnginesPath = null;
private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
/// <summary>
/// Is the entire simulator in the process of shutting down?
/// </summary>
@ -715,6 +717,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning;
m_Scene.EventManager.OnShutdown += OnShutdown;
// If region ready has been triggered, then the region had no scripts to compile and completed its other
// work.
m_Scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) m_InitialStartup = false; };
if (m_SleepTime > 0)
{
m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance),
@ -1269,7 +1275,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
if (instance!=null)
instance.Init();
bool runIt;
if (m_runFlags.TryGetValue(itemID, out runIt))
{
if (!runIt)
StopScript(itemID);
m_runFlags.Remove(itemID);
}
return true;
}
@ -1660,6 +1674,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
IScriptInstance instance = GetInstance(itemID);
if (instance != null)
instance.Start();
else
m_runFlags.AddOrUpdate(itemID, true, 240);
}
public void StopScript(UUID itemID)
@ -1671,6 +1687,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
instance.Stop(1000);
}
else
{
m_runFlags.AddOrUpdate(itemID, false, 240);
}
}
public DetectParams GetDetectParams(UUID itemID, int idx)

View File

@ -34,7 +34,7 @@ using Mono.Data.SqliteClient;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Region.UserStatistics
{

View File

@ -33,7 +33,7 @@ using System.Text;
using Mono.Data.SqliteClient;
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Region.UserStatistics

View File

@ -34,7 +34,7 @@ using System.Text.RegularExpressions;
using Mono.Data.SqliteClient;
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Region.UserStatistics
{

View File

@ -33,7 +33,7 @@ using System.Text;
using Mono.Data.SqliteClient;
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Region.UserStatistics
{

View File

@ -122,7 +122,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message);
m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception unwrapping folder list: ", e);
}
return fldrs;
@ -191,7 +191,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolderContent: {0}", e.Message);
m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolderContent: {0}", e.Message);
}
return inventory;
@ -432,7 +432,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetItem: {0}", e.Message);
m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e);
}
return null;
@ -456,7 +456,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolder: {0}", e.Message);
m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolder: ", e);
}
return null;
@ -474,7 +474,7 @@ namespace OpenSim.Services.Connectors
List<InventoryItemBase> items = new List<InventoryItemBase>();
foreach (Object o in ret.Values) // getting the values directly, we don't care about the keys item_i
foreach (Object o in ((Dictionary<string,object>)ret["ITEMS"]).Values)
items.Add(BuildItem((Dictionary<string, object>)o));
return items;
@ -525,7 +525,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetUserInventory: {0}", e.Message);
m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetUserInventory: ", e);
}
return inventory;
@ -574,7 +574,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building folder: {0}", e.Message);
m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception building folder: ", e);
}
return folder;
@ -613,11 +613,10 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building item: {0}", e.Message);
m_log.Error("[XINVENTORY CONNECTOR]: Exception building item: ", e);
}
return item;
}
}
}
}

View File

@ -190,7 +190,7 @@ namespace OpenSim.Tests.Common
= physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test");
testScene.RegionInfo.EstateSettings = new EstateSettings();
testScene.LoginsDisabled = false;
testScene.LoginsEnabled = true;
testScene.RegisterRegionWithGrid();
SceneManager.Add(testScene);

View File

@ -79,9 +79,27 @@ namespace OpenSim.Tests.Common
/// <param name="part"></param>
/// <returns>The item that was added</returns>
public static TaskInventoryItem AddScript(Scene scene, SceneObjectPart part)
{
return AddScript(scene, part, "scriptItem", "default { state_entry() { llSay(0, \"Hello World\"); } }");
}
/// <summary>
/// Add a simple script to the given part.
/// </summary>
/// <remarks>
/// TODO: Accept input for item and asset IDs to avoid mysterious script failures that try to use any of these
/// functions more than once in a test.
/// </remarks>
/// <param name="scene"></param>
/// <param name="part"></param>
/// <param name="scriptName">Name of the script to add</param>
/// <param name="scriptSource">LSL script source</param>
/// <returns>The item that was added</returns>
public static TaskInventoryItem AddScript(
Scene scene, SceneObjectPart part, string scriptName, string scriptSource)
{
AssetScriptText ast = new AssetScriptText();
ast.Source = "default { state_entry() { llSay(0, \"Hello World\"); } }";
ast.Source = scriptSource;
ast.Encode();
UUID assetUuid = new UUID("00000000-0000-0000-1000-000000000000");
@ -91,7 +109,7 @@ namespace OpenSim.Tests.Common
scene.AssetService.Store(asset);
TaskInventoryItem item
= new TaskInventoryItem
{ Name = "scriptItem", AssetID = assetUuid, ItemID = itemUuid,
{ Name = scriptName, AssetID = assetUuid, ItemID = itemUuid,
Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL };
part.Inventory.AddInventoryItem(item, true);

View File

@ -47,6 +47,9 @@ namespace pCampBot
{
Dictionary<UUID, Primitive> objects = Bot.Objects;
if (objects.Count <= 0)
return;
Primitive prim = objects.ElementAt(Bot.Random.Next(0, objects.Count - 1)).Value;
// This appears to be a typical message sent when a viewer user clicks a clickable object

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -112,6 +112,32 @@
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Framework.Monitoring" path="OpenSim/Framework/Monitoring" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="log4net" path="../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Files>
<Match pattern="*.cs" recurse="true"/>
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Framework.Servers.HttpServer" path="OpenSim/Framework/Servers/HttpServer" type="Library">
<Configuration name="Debug">
<Options>
@ -130,6 +156,7 @@
<Reference name="System.Xml"/>
<Reference name="System.Web"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
<Reference name="XMLRPC" path="../../../../bin/"/>
@ -235,30 +262,6 @@
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Framework.Statistics" path="OpenSim/Framework/Statistics" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Files>
<Match pattern="*.cs" recurse="true"/>
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Data" path="OpenSim/Data" type="Library">
<Configuration name="Debug">
<Options>
@ -436,7 +439,7 @@
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
<Reference name="XMLRPC" path="../../../bin/"/>
@ -640,39 +643,6 @@
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Region.Physics.BulletSPlugin" path="OpenSim/Region/Physics/BulletSPlugin" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="System.Xml"/>
<Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
<Reference name="Nini.dll" path="../../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
<Reference name="log4net.dll" path="../../../../bin/"/>
<Files>
<Match pattern="*.cs" recurse="true">
<Exclude name="Tests" pattern="Tests"/>
</Match>
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Region.Physics.Meshing" path="OpenSim/Region/Physics/Meshing" type="Library">
<Configuration name="Debug">
<Options>
@ -753,9 +723,9 @@
<Reference name="System.Xml"/>
<Reference name="System.Web"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="OpenMetaverse" path="../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../bin/"/>
@ -787,13 +757,13 @@
<Reference name="System"/>
<Reference name="System.Xml"/>
<Reference name="System.Web"/>
<Reference name="OpenSim.Data"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.AssetLoader.Filesystem"/>
<Reference name="OpenSim.Data"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
@ -839,10 +809,10 @@
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Data"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Serialization"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<!-- For scripting in funny languages by default -->
@ -1558,10 +1528,10 @@
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Serialization"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Server.Base"/>
@ -1649,11 +1619,11 @@
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Data"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="XMLRPC" path="../../../bin/"/>
<Reference name="Nini" path="../../../bin/"/>
@ -1686,15 +1656,15 @@
<Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../../../bin/"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Data"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.ClientStack"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="Nini" path="../../../../../bin/"/>
<Reference name="log4net" path="../../../../../bin/"/>
@ -1777,9 +1747,9 @@
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Data"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.ClientStack.LindenUDP"/>
<Reference name="OpenSim.Region.Framework"/>
@ -1834,6 +1804,64 @@
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.ConvexDecompositionDotNet" path="OpenSim/Region/Physics/ConvexDecompositionDotNet" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="System.Data"/>
<Reference name="System.Xml"/>
<Files>
<Match pattern="*.cs" recurse="true">
<Exclude name="Tests" pattern="Tests"/>
</Match>
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Region.Physics.BulletSPlugin" path="OpenSim/Region/Physics/BulletSPlugin" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../../bin/Physics/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="System.Xml"/>
<Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
<Reference name="Nini.dll" path="../../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
<Reference name="log4net.dll" path="../../../../bin/"/>
<Files>
<Match pattern="*.cs" recurse="true">
<Exclude name="Tests" pattern="Tests"/>
</Match>
</Files>
</Project>
<!-- OpenSim app -->
<Project frameworkVersion="v4_0" name="OpenSim" path="OpenSim/Region/Application" type="Exe">
<Configuration name="Debug">
@ -1857,15 +1885,15 @@
<Reference name="OpenMetaverse" path="../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Data"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.ClientStack"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Server.Base"/>
<Reference name="OpenSim.Services.Base"/>
<Reference name="OpenSim.Services.Interfaces"/>
@ -2378,10 +2406,11 @@
<Reference name="OpenSim"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/>
@ -2504,7 +2533,6 @@
</Files>
</Project>
<Project frameworkVersion="v4_0" name="OpenSim.Region.UserStatistics" path="OpenSim/Region/UserStatistics" type="Library">
<Configuration name="Debug">
<Options>
@ -2533,9 +2561,9 @@
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="Mono.Data.SqliteClient" path="../../../bin/"/>
<Reference name="Mono.Addins"/>
@ -3019,9 +3047,9 @@
<Reference name="OpenSim.Framework.Serialization"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
@ -3091,9 +3119,9 @@
<Reference name="OpenSim.Framework.Serialization"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.OptionalModules"/>
@ -3150,8 +3178,8 @@
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Region.ClientStack.LindenCaps"/>
<Reference name="OpenSim.Region.Framework"/>
@ -3207,9 +3235,9 @@
<Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.ClientStack.LindenCaps"/>
<Reference name="OpenSim.Region.ClientStack.LindenUDP"/>
<Reference name="OpenSim.Region.CoreModules"/>
@ -3244,7 +3272,7 @@
<Reference name="OpenMetaverseTypes" path="../../../../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Region.ClientStack"/>
<Reference name="OpenSim.Region.ClientStack.LindenUDP"/>
<Reference name="OpenSim.Region.CoreModules"/>

Some files were not shown because too many files have changed in this diff Show More