Merge branch 'master' of /home/opensim/var/repo/opensim
Conflicts: bin/Robust.HG.ini.example bin/Robust.ini.exampleintegration
commit
9f6e26d31d
|
@ -16,7 +16,7 @@ people that make the day to day of OpenSim happen.
|
||||||
* BlueWall (James Hughes)
|
* BlueWall (James Hughes)
|
||||||
* Nebadon Izumi (Michael Cerquoni, OSgrid)
|
* Nebadon Izumi (Michael Cerquoni, OSgrid)
|
||||||
* Snoopy Pfeffer
|
* Snoopy Pfeffer
|
||||||
* Richard Adams (Intel)
|
* Robert Adams (Intel)
|
||||||
|
|
||||||
= Core Developers Following the White Rabbit =
|
= Core Developers Following the White Rabbit =
|
||||||
Core developers who have temporarily (we hope) gone chasing the white rabbit.
|
Core developers who have temporarily (we hope) gone chasing the white rabbit.
|
||||||
|
|
|
@ -223,9 +223,9 @@ namespace OpenSim.Capabilities.Handlers
|
||||||
// sending back the last byte instead of an error status
|
// sending back the last byte instead of an error status
|
||||||
if (start >= texture.Data.Length)
|
if (start >= texture.Data.Length)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
"[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
|
// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
|
||||||
texture.ID, start, texture.Data.Length);
|
// texture.ID, start, texture.Data.Length);
|
||||||
|
|
||||||
// Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
|
// Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
|
||||||
// Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
|
// Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
|
||||||
|
|
|
@ -85,21 +85,6 @@ namespace OpenSim.Data
|
||||||
List<RegionData> GetHyperlinks(UUID scopeID);
|
List<RegionData> GetHyperlinks(UUID scopeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum RegionFlags : int
|
|
||||||
{
|
|
||||||
DefaultRegion = 1, // Used for new Rez. Random if multiple defined
|
|
||||||
FallbackRegion = 2, // Regions we redirect to when the destination is down
|
|
||||||
RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false
|
|
||||||
NoDirectLogin = 8, // Region unavailable for direct logins (by name)
|
|
||||||
Persistent = 16, // Don't remove on unregister
|
|
||||||
LockedOut = 32, // Don't allow registration
|
|
||||||
NoMove = 64, // Don't allow moving this region
|
|
||||||
Reservation = 128, // This is an inactive reservation
|
|
||||||
Authenticate = 256, // Require authentication
|
|
||||||
Hyperlink = 512 // Record represents a HG link
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RegionDataDistanceCompare : IComparer<RegionData>
|
public class RegionDataDistanceCompare : IComparer<RegionData>
|
||||||
{
|
{
|
||||||
private Vector2 m_origin;
|
private Vector2 m_origin;
|
||||||
|
|
|
@ -37,6 +37,7 @@ using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using RegionFlags = OpenSim.Framework.RegionFlags;
|
||||||
|
|
||||||
namespace OpenSim.Data.MSSQL
|
namespace OpenSim.Data.MSSQL
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,11 +30,11 @@ using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Data;
|
using OpenSim.Data;
|
||||||
using MySql.Data.MySqlClient;
|
using RegionFlags = OpenSim.Framework.RegionFlags;
|
||||||
|
|
||||||
namespace OpenSim.Data.MySQL
|
namespace OpenSim.Data.MySQL
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,7 @@ using OpenSim.Framework;
|
||||||
using OpenSim.Data;
|
using OpenSim.Data;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
using RegionFlags = OpenSim.Framework.RegionFlags;
|
||||||
|
|
||||||
namespace OpenSim.Data.Null
|
namespace OpenSim.Data.Null
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* 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 log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
public class ConsoleUtil
|
||||||
|
{
|
||||||
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public const string MinRawConsoleVectorValue = "-~";
|
||||||
|
public const string MaxRawConsoleVectorValue = "~";
|
||||||
|
|
||||||
|
public const string VectorSeparator = ",";
|
||||||
|
public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='rawConsoleVector'>/param>
|
||||||
|
/// <param name='vector'></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector)
|
||||||
|
{
|
||||||
|
return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a maximum vector input from the console to an OpenMetaverse.Vector3
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='rawConsoleVector'>/param>
|
||||||
|
/// <param name='vector'></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector)
|
||||||
|
{
|
||||||
|
return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a vector input from the console to an OpenMetaverse.Vector3
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='rawConsoleVector'>
|
||||||
|
/// A string in the form <x>,<y>,<z> where there is no space between values.
|
||||||
|
/// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value
|
||||||
|
/// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40)
|
||||||
|
/// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue
|
||||||
|
/// Other than that, component values must be numeric.
|
||||||
|
/// </param>
|
||||||
|
/// <param name='blankComponentFunc'></param>
|
||||||
|
/// <param name='vector'></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryParseConsoleVector(
|
||||||
|
string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector)
|
||||||
|
{
|
||||||
|
List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList();
|
||||||
|
|
||||||
|
if (components.Count < 1 || components.Count > 3)
|
||||||
|
{
|
||||||
|
vector = Vector3.Zero;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = components.Count; i < 3; i++)
|
||||||
|
components.Add("");
|
||||||
|
|
||||||
|
List<string> semiDigestedComponents
|
||||||
|
= components.ConvertAll<string>(
|
||||||
|
c =>
|
||||||
|
{
|
||||||
|
if (c == "")
|
||||||
|
return blankComponentFunc.Invoke(c);
|
||||||
|
else if (c == MaxRawConsoleVectorValue)
|
||||||
|
return float.MaxValue.ToString();
|
||||||
|
else if (c == MinRawConsoleVectorValue)
|
||||||
|
return float.MinValue.ToString();
|
||||||
|
else
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
|
||||||
|
string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray());
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector);
|
||||||
|
|
||||||
|
return Vector3.TryParse(semiDigestedConsoleVector, out vector);
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,6 @@ namespace OpenSim.Framework
|
||||||
public Vector3 Position;
|
public Vector3 Position;
|
||||||
public byte[] binaryBucket;
|
public byte[] binaryBucket;
|
||||||
|
|
||||||
|
|
||||||
public uint ParentEstateID;
|
public uint ParentEstateID;
|
||||||
public Guid RegionID;
|
public Guid RegionID;
|
||||||
public uint timestamp;
|
public uint timestamp;
|
||||||
|
@ -58,7 +57,7 @@ namespace OpenSim.Framework
|
||||||
string _fromAgentName, UUID _toAgentID,
|
string _fromAgentName, UUID _toAgentID,
|
||||||
byte _dialog, bool _fromGroup, string _message,
|
byte _dialog, bool _fromGroup, string _message,
|
||||||
UUID _imSessionID, bool _offline, Vector3 _position,
|
UUID _imSessionID, bool _offline, Vector3 _position,
|
||||||
byte[] _binaryBucket)
|
byte[] _binaryBucket, bool addTimestamp)
|
||||||
{
|
{
|
||||||
fromAgentID = _fromAgentID.Guid;
|
fromAgentID = _fromAgentID.Guid;
|
||||||
fromAgentName = _fromAgentName;
|
fromAgentName = _fromAgentName;
|
||||||
|
@ -79,7 +78,9 @@ namespace OpenSim.Framework
|
||||||
ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID;
|
ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID;
|
||||||
RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid;
|
RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid;
|
||||||
}
|
}
|
||||||
timestamp = (uint)Util.UnixTimeSinceEpoch();
|
|
||||||
|
if (addTimestamp)
|
||||||
|
timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GridInstantMessage(IScene scene, UUID _fromAgentID,
|
public GridInstantMessage(IScene scene, UUID _fromAgentID,
|
||||||
|
@ -87,7 +88,7 @@ namespace OpenSim.Framework
|
||||||
string _message, bool _offline,
|
string _message, bool _offline,
|
||||||
Vector3 _position) : this(scene, _fromAgentID, _fromAgentName,
|
Vector3 _position) : this(scene, _fromAgentID, _fromAgentName,
|
||||||
_toAgentID, _dialog, false, _message,
|
_toAgentID, _dialog, false, _message,
|
||||||
_fromAgentID ^ _toAgentID, _offline, _position, new byte[0])
|
_fromAgentID ^ _toAgentID, _offline, _position, new byte[0], true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -805,8 +805,23 @@ namespace OpenSim.Framework
|
||||||
event Action<IClientAPI> OnRegionHandShakeReply;
|
event Action<IClientAPI> OnRegionHandShakeReply;
|
||||||
event GenericCall1 OnRequestWearables;
|
event GenericCall1 OnRequestWearables;
|
||||||
event Action<IClientAPI, bool> OnCompleteMovementToRegion;
|
event Action<IClientAPI, bool> OnCompleteMovementToRegion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when an AgentUpdate message is received and before OnAgentUpdate.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates.
|
||||||
|
/// </remarks>
|
||||||
event UpdateAgent OnPreAgentUpdate;
|
event UpdateAgent OnPreAgentUpdate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when an AgentUpdate message is received and after OnPreAgentUpdate.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates.
|
||||||
|
/// </remarks>
|
||||||
event UpdateAgent OnAgentUpdate;
|
event UpdateAgent OnAgentUpdate;
|
||||||
|
|
||||||
event AgentRequestSit OnAgentRequestSit;
|
event AgentRequestSit OnAgentRequestSit;
|
||||||
event AgentSit OnAgentSit;
|
event AgentSit OnAgentSit;
|
||||||
event AvatarPickerRequest OnAvatarPickerRequest;
|
event AvatarPickerRequest OnAvatarPickerRequest;
|
||||||
|
|
|
@ -49,7 +49,11 @@ namespace OpenSim.Framework.Monitoring
|
||||||
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
|
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
|
||||||
|
|
||||||
sb.AppendFormat(
|
sb.AppendFormat(
|
||||||
"OpenSim object memory churn : {0} MB/s\n",
|
"OpenSim last object memory churn : {0} MB/s\n",
|
||||||
|
Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
|
||||||
|
|
||||||
|
sb.AppendFormat(
|
||||||
|
"OpenSim average object memory churn : {0} MB/s\n",
|
||||||
Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
|
Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
|
||||||
|
|
||||||
sb.AppendFormat(
|
sb.AppendFormat(
|
||||||
|
|
|
@ -60,13 +60,21 @@ namespace OpenSim.Framework.Monitoring
|
||||||
private static bool m_enabled;
|
private static bool m_enabled;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Average memory churn in bytes per millisecond.
|
/// Last memory churn in bytes per millisecond.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static double AverageMemoryChurn
|
public static double AverageMemoryChurn
|
||||||
{
|
{
|
||||||
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
|
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Average memory churn in bytes per millisecond.
|
||||||
|
/// </summary>
|
||||||
|
public static double LastMemoryChurn
|
||||||
|
{
|
||||||
|
get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of statistical samples.
|
/// Maximum number of statistical samples.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -355,10 +355,25 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append(
|
sb.Append(
|
||||||
string.Format(
|
string.Format(
|
||||||
"{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}",
|
"{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}\n\n",
|
||||||
inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
|
inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
|
||||||
netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
|
netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
|
||||||
sb.Append(Environment.NewLine);
|
|
||||||
|
Dictionary<string, Dictionary<string, Stat>> sceneStats;
|
||||||
|
|
||||||
|
if (StatsManager.TryGetStats("scene", out sceneStats))
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats)
|
||||||
|
{
|
||||||
|
foreach (Stat stat in kvp.Value.Values)
|
||||||
|
{
|
||||||
|
if (stat.Verbosity == StatVerbosity.Info)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -32,6 +35,24 @@ namespace OpenSim.Framework.Monitoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StatsManager
|
public class StatsManager
|
||||||
{
|
{
|
||||||
|
// Subcommand used to list other stats.
|
||||||
|
public const string AllSubCommand = "all";
|
||||||
|
|
||||||
|
// Subcommand used to list other stats.
|
||||||
|
public const string ListSubCommand = "list";
|
||||||
|
|
||||||
|
// All subcommands
|
||||||
|
public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registered stats categorized by category/container/shortname
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Do not add or remove directly from this dictionary.
|
||||||
|
/// </remarks>
|
||||||
|
public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats
|
||||||
|
= new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>();
|
||||||
|
|
||||||
private static AssetStatsCollector assetStats;
|
private static AssetStatsCollector assetStats;
|
||||||
private static UserStatsCollector userStats;
|
private static UserStatsCollector userStats;
|
||||||
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
|
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
|
||||||
|
@ -40,6 +61,75 @@ namespace OpenSim.Framework.Monitoring
|
||||||
public static UserStatsCollector UserStats { get { return userStats; } }
|
public static UserStatsCollector UserStats { get { return userStats; } }
|
||||||
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
|
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
|
||||||
|
|
||||||
|
public static void RegisterConsoleCommands(ICommandConsole console)
|
||||||
|
{
|
||||||
|
console.Commands.AddCommand(
|
||||||
|
"General",
|
||||||
|
false,
|
||||||
|
"show stats",
|
||||||
|
"show stats [list|all|<category>]",
|
||||||
|
"Show statistical information for this server",
|
||||||
|
"If no final argument is specified then legacy statistics information is currently shown.\n"
|
||||||
|
+ "If list is specified then statistic categories are shown.\n"
|
||||||
|
+ "If all is specified then all registered statistics are shown.\n"
|
||||||
|
+ "If a category name is specified then only statistics from that category are shown.\n"
|
||||||
|
+ "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
|
||||||
|
HandleShowStatsCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleShowStatsCommand(string module, string[] cmd)
|
||||||
|
{
|
||||||
|
ICommandConsole con = MainConsole.Instance;
|
||||||
|
|
||||||
|
if (cmd.Length > 2)
|
||||||
|
{
|
||||||
|
var categoryName = cmd[2];
|
||||||
|
|
||||||
|
if (categoryName == AllSubCommand)
|
||||||
|
{
|
||||||
|
foreach (var category in RegisteredStats.Values)
|
||||||
|
{
|
||||||
|
OutputCategoryStatsToConsole(con, category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (categoryName == ListSubCommand)
|
||||||
|
{
|
||||||
|
con.Output("Statistic categories available are:");
|
||||||
|
foreach (string category in RegisteredStats.Keys)
|
||||||
|
con.OutputFormat(" {0}", category);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, Dictionary<string, Stat>> category;
|
||||||
|
if (!RegisteredStats.TryGetValue(categoryName, out category))
|
||||||
|
{
|
||||||
|
con.OutputFormat("No such category as {0}", categoryName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutputCategoryStatsToConsole(con, category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Legacy
|
||||||
|
con.Output(SimExtraStats.Report());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OutputCategoryStatsToConsole(
|
||||||
|
ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category)
|
||||||
|
{
|
||||||
|
foreach (var container in category.Values)
|
||||||
|
{
|
||||||
|
foreach (Stat stat in container.Values)
|
||||||
|
{
|
||||||
|
con.Output(stat.ToConsoleString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start collecting statistics related to assets.
|
/// Start collecting statistics related to assets.
|
||||||
/// Should only be called once.
|
/// Should only be called once.
|
||||||
|
@ -61,5 +151,224 @@ namespace OpenSim.Framework.Monitoring
|
||||||
|
|
||||||
return userStats;
|
return userStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a statistic.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='stat'></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool RegisterStat(Stat stat)
|
||||||
|
{
|
||||||
|
Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
|
||||||
|
Dictionary<string, Stat> container = null, newContainer;
|
||||||
|
|
||||||
|
lock (RegisteredStats)
|
||||||
|
{
|
||||||
|
// Stat name is not unique across category/container/shortname key.
|
||||||
|
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
|
||||||
|
// in a class are run in the same instance of the VM.
|
||||||
|
if (TryGetStat(stat, out category, out container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
|
||||||
|
// This means that we don't need to lock or copy them on iteration, which will be a much more
|
||||||
|
// common operation after startup.
|
||||||
|
if (container != null)
|
||||||
|
newContainer = new Dictionary<string, Stat>(container);
|
||||||
|
else
|
||||||
|
newContainer = new Dictionary<string, Stat>();
|
||||||
|
|
||||||
|
if (category != null)
|
||||||
|
newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
|
||||||
|
else
|
||||||
|
newCategory = new Dictionary<string, Dictionary<string, Stat>>();
|
||||||
|
|
||||||
|
newContainer[stat.ShortName] = stat;
|
||||||
|
newCategory[stat.Container] = newContainer;
|
||||||
|
RegisteredStats[stat.Category] = newCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deregister a statistic
|
||||||
|
/// </summary>>
|
||||||
|
/// <param name='stat'></param>
|
||||||
|
/// <returns></returns
|
||||||
|
public static bool DeregisterStat(Stat stat)
|
||||||
|
{
|
||||||
|
Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
|
||||||
|
Dictionary<string, Stat> container = null, newContainer;
|
||||||
|
|
||||||
|
lock (RegisteredStats)
|
||||||
|
{
|
||||||
|
if (!TryGetStat(stat, out category, out container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
newContainer = new Dictionary<string, Stat>(container);
|
||||||
|
newContainer.Remove(stat.UniqueName);
|
||||||
|
|
||||||
|
newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
|
||||||
|
newCategory.Remove(stat.Container);
|
||||||
|
|
||||||
|
newCategory[stat.Container] = newContainer;
|
||||||
|
RegisteredStats[stat.Category] = newCategory;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats)
|
||||||
|
{
|
||||||
|
return RegisteredStats.TryGetValue(category, out stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetStat(
|
||||||
|
Stat stat,
|
||||||
|
out Dictionary<string, Dictionary<string, Stat>> category,
|
||||||
|
out Dictionary<string, Stat> container)
|
||||||
|
{
|
||||||
|
category = null;
|
||||||
|
container = null;
|
||||||
|
|
||||||
|
lock (RegisteredStats)
|
||||||
|
{
|
||||||
|
if (RegisteredStats.TryGetValue(stat.Category, out category))
|
||||||
|
{
|
||||||
|
if (category.TryGetValue(stat.Container, out container))
|
||||||
|
{
|
||||||
|
if (container.ContainsKey(stat.ShortName))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verbosity of stat.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Info will always be displayed.
|
||||||
|
/// </remarks>
|
||||||
|
public enum StatVerbosity
|
||||||
|
{
|
||||||
|
Debug,
|
||||||
|
Info
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds individual static details
|
||||||
|
/// </summary>
|
||||||
|
public class Stat
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unique stat name used for indexing. Each ShortName in a Category must be unique.
|
||||||
|
/// </summary>
|
||||||
|
public string UniqueName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Category of this stat (e.g. cache, scene, etc).
|
||||||
|
/// </summary>
|
||||||
|
public string Category { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Containing name for this stat.
|
||||||
|
/// FIXME: In the case of a scene, this is currently the scene name (though this leaves
|
||||||
|
/// us with a to-be-resolved problem of non-unique region names).
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The container.
|
||||||
|
/// </value>
|
||||||
|
public string Container { get; private set; }
|
||||||
|
|
||||||
|
public StatVerbosity Verbosity { get; private set; }
|
||||||
|
public string ShortName { get; private set; }
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public string Description { get; private set; }
|
||||||
|
public virtual string UnitName { get; private set; }
|
||||||
|
|
||||||
|
public virtual double Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param>
|
||||||
|
/// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param>
|
||||||
|
/// <param name='unitName'>
|
||||||
|
/// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
|
||||||
|
/// e.g. " frames"
|
||||||
|
/// </param>
|
||||||
|
/// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param>
|
||||||
|
/// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param>
|
||||||
|
/// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param>
|
||||||
|
/// <param name='description'>Description of stat</param>
|
||||||
|
public Stat(
|
||||||
|
string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description)
|
||||||
|
{
|
||||||
|
if (StatsManager.SubCommands.Contains(category))
|
||||||
|
throw new Exception(
|
||||||
|
string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
|
||||||
|
|
||||||
|
ShortName = shortName;
|
||||||
|
Name = name;
|
||||||
|
UnitName = unitName;
|
||||||
|
Category = category;
|
||||||
|
Container = container;
|
||||||
|
Verbosity = verbosity;
|
||||||
|
Description = description;
|
||||||
|
|
||||||
|
UniqueName = GenUniqueName(Container, Category, ShortName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenUniqueName(string container, string category, string shortName)
|
||||||
|
{
|
||||||
|
return string.Format("{0}+{1}+{2}", container, category, shortName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string ToConsoleString()
|
||||||
|
{
|
||||||
|
return string.Format(
|
||||||
|
"{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PercentageStat : Stat
|
||||||
|
{
|
||||||
|
public int Antecedent { get; set; }
|
||||||
|
public int Consequent { get; set; }
|
||||||
|
|
||||||
|
public override double Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int c = Consequent;
|
||||||
|
|
||||||
|
// Avoid any chance of a multi-threaded divide-by-zero
|
||||||
|
if (c == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (double)Antecedent / c * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
throw new Exception("Cannot set value on a PercentageStat");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PercentageStat(
|
||||||
|
string shortName, string name, string category, string container, StatVerbosity verbosity, string description)
|
||||||
|
: base(shortName, name, "%", category, container, verbosity, description) {}
|
||||||
|
|
||||||
|
public override string ToConsoleString()
|
||||||
|
{
|
||||||
|
return string.Format(
|
||||||
|
"{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})",
|
||||||
|
Category, Container, ShortName, Value, UnitName, Antecedent, Consequent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -231,7 +231,25 @@ namespace OpenSim.Framework.Monitoring
|
||||||
private static bool RemoveThread(int threadID)
|
private static bool RemoveThread(int threadID)
|
||||||
{
|
{
|
||||||
lock (m_threads)
|
lock (m_threads)
|
||||||
return m_threads.Remove(threadID);
|
{
|
||||||
|
ThreadWatchdogInfo twi;
|
||||||
|
if (m_threads.TryGetValue(threadID, out twi))
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
|
||||||
|
|
||||||
|
m_threads.Remove(threadID);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool AbortThread(int threadID)
|
public static bool AbortThread(int threadID)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Naive pool implementation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Currently assumes that objects are in a useable state when returned.
|
||||||
|
/// </remarks>
|
||||||
|
public class Pool<T>
|
||||||
|
{
|
||||||
|
private Stack<T> m_pool;
|
||||||
|
|
||||||
|
private int m_maxPoolSize;
|
||||||
|
|
||||||
|
private Func<T> m_createFunction;
|
||||||
|
|
||||||
|
public Pool(Func<T> createFunction, int maxSize)
|
||||||
|
{
|
||||||
|
m_maxPoolSize = maxSize;
|
||||||
|
m_createFunction = createFunction;
|
||||||
|
m_pool = new Stack<T>(m_maxPoolSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetObject()
|
||||||
|
{
|
||||||
|
lock (m_pool)
|
||||||
|
{
|
||||||
|
if (m_pool.Count > 0)
|
||||||
|
return m_pool.Pop();
|
||||||
|
else
|
||||||
|
return m_createFunction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReturnObject(T obj)
|
||||||
|
{
|
||||||
|
lock (m_pool)
|
||||||
|
{
|
||||||
|
if (m_pool.Count >= m_maxPoolSize)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
m_pool.Push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Region flags used internally by OpenSimulator to store installation specific information about regions.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Don't confuse with OpenMetaverse.RegionFlags which are client facing flags (i.e. they go over the wire).
|
||||||
|
/// Returned by IGridService.GetRegionFlags()
|
||||||
|
/// </remarks>
|
||||||
|
[Flags]
|
||||||
|
public enum RegionFlags : int
|
||||||
|
{
|
||||||
|
DefaultRegion = 1, // Used for new Rez. Random if multiple defined
|
||||||
|
FallbackRegion = 2, // Regions we redirect to when the destination is down
|
||||||
|
RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false
|
||||||
|
NoDirectLogin = 8, // Region unavailable for direct logins (by name)
|
||||||
|
Persistent = 16, // Don't remove on unregister
|
||||||
|
LockedOut = 32, // Don't allow registration
|
||||||
|
NoMove = 64, // Don't allow moving this region
|
||||||
|
Reservation = 128, // This is an inactive reservation
|
||||||
|
Authenticate = 256, // Require authentication
|
||||||
|
Hyperlink = 512 // Record represents a HG link
|
||||||
|
}
|
||||||
|
}
|
|
@ -96,11 +96,6 @@ namespace OpenSim.Framework.Servers
|
||||||
get { return m_httpServer; }
|
get { return m_httpServer; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Holds the non-viewer statistics collection object for this service/server
|
|
||||||
/// </summary>
|
|
||||||
protected IStatsCollector m_stats;
|
|
||||||
|
|
||||||
public BaseOpenSimServer()
|
public BaseOpenSimServer()
|
||||||
{
|
{
|
||||||
m_startuptime = DateTime.Now;
|
m_startuptime = DateTime.Now;
|
||||||
|
@ -177,10 +172,6 @@ namespace OpenSim.Framework.Servers
|
||||||
"show info",
|
"show info",
|
||||||
"Show general information about the server", HandleShow);
|
"Show general information about the server", HandleShow);
|
||||||
|
|
||||||
m_console.Commands.AddCommand("General", false, "show stats",
|
|
||||||
"show stats",
|
|
||||||
"Show statistics", HandleShow);
|
|
||||||
|
|
||||||
m_console.Commands.AddCommand("General", false, "show threads",
|
m_console.Commands.AddCommand("General", false, "show threads",
|
||||||
"show threads",
|
"show threads",
|
||||||
"Show thread status", HandleShow);
|
"Show thread status", HandleShow);
|
||||||
|
@ -226,12 +217,7 @@ namespace OpenSim.Framework.Servers
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n");
|
StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n");
|
||||||
sb.Append(GetUptimeReport());
|
sb.Append(GetUptimeReport());
|
||||||
|
sb.Append(StatsManager.SimExtraStats.Report());
|
||||||
if (m_stats != null)
|
|
||||||
{
|
|
||||||
sb.Append(m_stats.Report());
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.Append(GetThreadsReport());
|
sb.Append(GetThreadsReport());
|
||||||
|
|
||||||
|
@ -382,10 +368,6 @@ namespace OpenSim.Framework.Servers
|
||||||
{
|
{
|
||||||
Notice("set log level [level] - change the console logging level only. For example, off or debug.");
|
Notice("set log level [level] - change the console logging level only. For example, off or debug.");
|
||||||
Notice("show info - show server information (e.g. startup path).");
|
Notice("show info - show server information (e.g. startup path).");
|
||||||
|
|
||||||
if (m_stats != null)
|
|
||||||
Notice("show stats - show statistical information for this server");
|
|
||||||
|
|
||||||
Notice("show threads - list tracked threads");
|
Notice("show threads - list tracked threads");
|
||||||
Notice("show uptime - show server startup time and uptime.");
|
Notice("show uptime - show server startup time and uptime.");
|
||||||
Notice("show version - show server version.");
|
Notice("show version - show server version.");
|
||||||
|
@ -409,11 +391,6 @@ namespace OpenSim.Framework.Servers
|
||||||
ShowInfo();
|
ShowInfo();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "stats":
|
|
||||||
if (m_stats != null)
|
|
||||||
Notice(m_stats.Report());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "threads":
|
case "threads":
|
||||||
Notice(GetThreadsReport());
|
Notice(GetThreadsReport());
|
||||||
break;
|
break;
|
||||||
|
@ -605,7 +582,6 @@ namespace OpenSim.Framework.Servers
|
||||||
public string osSecret {
|
public string osSecret {
|
||||||
// Secret uuid for the simulator
|
// Secret uuid for the simulator
|
||||||
get { return m_osSecret; }
|
get { return m_osSecret; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string StatReport(IOSHttpRequest httpRequest)
|
public string StatReport(IOSHttpRequest httpRequest)
|
||||||
|
@ -613,11 +589,11 @@ namespace OpenSim.Framework.Servers
|
||||||
// If we catch a request for "callback", wrap the response in the value for jsonp
|
// If we catch a request for "callback", wrap the response in the value for jsonp
|
||||||
if (httpRequest.Query.ContainsKey("callback"))
|
if (httpRequest.Query.ContainsKey("callback"))
|
||||||
{
|
{
|
||||||
return httpRequest.Query["callback"].ToString() + "(" + m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");";
|
return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version);
|
return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -648,7 +648,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
// Every month or so this will wrap and give bad numbers, not really a problem
|
// Every month or so this will wrap and give bad numbers, not really a problem
|
||||||
// since its just for reporting
|
// since its just for reporting
|
||||||
int tickdiff = requestEndTick - requestStartTick;
|
int tickdiff = requestEndTick - requestStartTick;
|
||||||
if (tickdiff > 3000 && requestHandler.Name != "GetTexture")
|
if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture")
|
||||||
{
|
{
|
||||||
m_log.InfoFormat(
|
m_log.InfoFormat(
|
||||||
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
|
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
|
||||||
|
|
|
@ -533,6 +533,19 @@ namespace OpenSim.Framework
|
||||||
return (x + y - (min >> 1) - (min >> 2) + (min >> 4));
|
return (x + y - (min >> 1) - (min >> 2) + (min >> 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether a point is inside a bounding box.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='v'>/param>
|
||||||
|
/// <param name='min'></param>
|
||||||
|
/// <param name='max'></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsInsideBox(Vector3 v, Vector3 min, Vector3 max)
|
||||||
|
{
|
||||||
|
return v.X >= min.X & v.Y >= min.Y && v.Z >= min.Z
|
||||||
|
&& v.X <= max.X && v.Y <= max.Y && v.Z <= max.Z;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Are the co-ordinates of the new region visible from the old region?
|
/// Are the co-ordinates of the new region visible from the old region?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -254,8 +254,14 @@ namespace OpenSim
|
||||||
m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
|
m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
|
||||||
|
|
||||||
m_console.Commands.AddCommand("Debug", false, "debug scene",
|
m_console.Commands.AddCommand("Debug", false, "debug scene",
|
||||||
"debug scene <scripting> <collisions> <physics>",
|
"debug scene active|collisions|physics|scripting|teleport true|false",
|
||||||
"Turn on scene debugging", Debug);
|
"Turn on scene debugging.",
|
||||||
|
"If active is false then main scene update and maintenance loops are suspended.\n"
|
||||||
|
+ "If collisions is false then collisions with other objects are turned off.\n"
|
||||||
|
+ "If physics is false then all physics objects are non-physical.\n"
|
||||||
|
+ "If scripting is false then no scripting operations happen.\n"
|
||||||
|
+ "If teleport is true then some extra teleport debug information is logged.",
|
||||||
|
Debug);
|
||||||
|
|
||||||
m_console.Commands.AddCommand("General", false, "change region",
|
m_console.Commands.AddCommand("General", false, "change region",
|
||||||
"change region <region name>",
|
"change region <region name>",
|
||||||
|
@ -930,7 +936,8 @@ namespace OpenSim
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false");
|
MainConsole.Instance.Output(
|
||||||
|
"Usage: debug scene active|scripting|collisions|physics|teleport true|false");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -223,8 +223,6 @@ namespace OpenSim
|
||||||
|
|
||||||
base.StartupSpecific();
|
base.StartupSpecific();
|
||||||
|
|
||||||
m_stats = StatsManager.SimExtraStats;
|
|
||||||
|
|
||||||
// Create a ModuleLoader instance
|
// Create a ModuleLoader instance
|
||||||
m_moduleLoader = new ModuleLoader(m_config.Source);
|
m_moduleLoader = new ModuleLoader(m_config.Source);
|
||||||
|
|
||||||
|
@ -234,51 +232,51 @@ namespace OpenSim
|
||||||
plugin.PostInitialise();
|
plugin.PostInitialise();
|
||||||
}
|
}
|
||||||
|
|
||||||
AddPluginCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddPluginCommands()
|
|
||||||
{
|
|
||||||
// If console exists add plugin commands.
|
|
||||||
if (m_console != null)
|
if (m_console != null)
|
||||||
{
|
{
|
||||||
List<string> topics = GetHelpTopics();
|
StatsManager.RegisterConsoleCommands(m_console);
|
||||||
|
AddPluginCommands(m_console);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (string topic in topics)
|
protected virtual void AddPluginCommands(CommandConsole console)
|
||||||
|
{
|
||||||
|
List<string> topics = GetHelpTopics();
|
||||||
|
|
||||||
|
foreach (string topic in topics)
|
||||||
|
{
|
||||||
|
string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1);
|
||||||
|
|
||||||
|
// This is a hack to allow the user to enter the help command in upper or lowercase. This will go
|
||||||
|
// away at some point.
|
||||||
|
console.Commands.AddCommand(capitalizedTopic, false, "help " + topic,
|
||||||
|
"help " + capitalizedTopic,
|
||||||
|
"Get help on plugin command '" + topic + "'",
|
||||||
|
HandleCommanderHelp);
|
||||||
|
console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
|
||||||
|
"help " + capitalizedTopic,
|
||||||
|
"Get help on plugin command '" + topic + "'",
|
||||||
|
HandleCommanderHelp);
|
||||||
|
|
||||||
|
ICommander commander = null;
|
||||||
|
|
||||||
|
Scene s = SceneManager.CurrentOrFirstScene;
|
||||||
|
|
||||||
|
if (s != null && s.GetCommanders() != null)
|
||||||
{
|
{
|
||||||
string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1);
|
if (s.GetCommanders().ContainsKey(topic))
|
||||||
|
commander = s.GetCommanders()[topic];
|
||||||
|
}
|
||||||
|
|
||||||
// This is a hack to allow the user to enter the help command in upper or lowercase. This will go
|
if (commander == null)
|
||||||
// away at some point.
|
continue;
|
||||||
m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic,
|
|
||||||
"help " + capitalizedTopic,
|
|
||||||
"Get help on plugin command '" + topic + "'",
|
|
||||||
HandleCommanderHelp);
|
|
||||||
m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
|
|
||||||
"help " + capitalizedTopic,
|
|
||||||
"Get help on plugin command '" + topic + "'",
|
|
||||||
HandleCommanderHelp);
|
|
||||||
|
|
||||||
ICommander commander = null;
|
foreach (string command in commander.Commands.Keys)
|
||||||
|
{
|
||||||
Scene s = SceneManager.CurrentOrFirstScene;
|
console.Commands.AddCommand(capitalizedTopic, false,
|
||||||
|
topic + " " + command,
|
||||||
if (s != null && s.GetCommanders() != null)
|
topic + " " + commander.Commands[command].ShortHelp(),
|
||||||
{
|
String.Empty, HandleCommanderCommand);
|
||||||
if (s.GetCommanders().ContainsKey(topic))
|
|
||||||
commander = s.GetCommanders()[topic];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commander == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (string command in commander.Commands.Keys)
|
|
||||||
{
|
|
||||||
m_console.Commands.AddCommand(capitalizedTopic, false,
|
|
||||||
topic + " " + command,
|
|
||||||
topic + " " + commander.Commands[command].ShortHelp(),
|
|
||||||
String.Empty, HandleCommanderCommand);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,8 +163,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
m_HostCapsObj.RegisterHandler(
|
m_HostCapsObj.RegisterHandler(
|
||||||
"SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
|
"SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
|
||||||
|
|
||||||
m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
"[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
|
// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
|
||||||
|
|
||||||
//m_capsHandlers["MapLayer"] =
|
//m_capsHandlers["MapLayer"] =
|
||||||
// new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
|
// new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
|
||||||
|
@ -254,11 +254,12 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
public string SeedCapRequest(string request, string path, string param,
|
public string SeedCapRequest(string request, string path, string param,
|
||||||
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
{
|
{
|
||||||
// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName);
|
m_log.DebugFormat(
|
||||||
|
"[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
|
||||||
|
|
||||||
if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
|
if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
m_log.WarnFormat(
|
||||||
"[CAPS]: Unauthorized CAPS client {0} from {1}",
|
"[CAPS]: Unauthorized CAPS client {0} from {1}",
|
||||||
m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
|
m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
//scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
|
//scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
|
||||||
|
|
||||||
scene.EventManager.OnNewClient += OnNewClient;
|
// scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
|
||||||
// TODO: Leaving these open, or closing them when we
|
// TODO: Leaving these open, or closing them when we
|
||||||
// become a child is incorrect. It messes up TP in a big
|
// become a child is incorrect. It messes up TP in a big
|
||||||
|
@ -102,6 +102,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
// circuit is there.
|
// circuit is there.
|
||||||
|
|
||||||
scene.EventManager.OnClientClosed += ClientClosed;
|
scene.EventManager.OnClientClosed += ClientClosed;
|
||||||
|
|
||||||
scene.EventManager.OnMakeChildAgent += MakeChildAgent;
|
scene.EventManager.OnMakeChildAgent += MakeChildAgent;
|
||||||
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
||||||
|
|
||||||
|
@ -110,10 +111,10 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
false,
|
false,
|
||||||
"debug eq",
|
"debug eq",
|
||||||
"debug eq [0|1|2]",
|
"debug eq [0|1|2]",
|
||||||
"Turn on event queue debugging"
|
"Turn on event queue debugging\n"
|
||||||
+ "<= 0 - turns off all event queue logging"
|
+ " <= 0 - turns off all event queue logging\n"
|
||||||
+ ">= 1 - turns on outgoing event logging"
|
+ " >= 1 - turns on outgoing event logging\n"
|
||||||
+ ">= 2 - turns on poll notification",
|
+ " >= 2 - turns on poll notification",
|
||||||
HandleDebugEq);
|
HandleDebugEq);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -226,16 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void OnNewClient(IClientAPI client)
|
|
||||||
{
|
|
||||||
//client.OnLogout += ClientClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// private void ClientClosed(IClientAPI client)
|
|
||||||
// {
|
|
||||||
// ClientClosed(client.AgentId);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void ClientClosed(UUID agentID, Scene scene)
|
private void ClientClosed(UUID agentID, Scene scene)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
|
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
|
||||||
|
|
|
@ -107,7 +107,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
UUID capID = UUID.Random();
|
UUID capID = UUID.Random();
|
||||||
|
|
||||||
m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
|
// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
|
||||||
caps.RegisterHandler(
|
caps.RegisterHandler(
|
||||||
"SimConsoleAsync",
|
"SimConsoleAsync",
|
||||||
new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene));
|
new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene));
|
||||||
|
|
|
@ -45,7 +45,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public Packet Packet;
|
public Packet Packet;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor
|
/// No arg constructor.
|
||||||
|
/// </summary>
|
||||||
|
public IncomingPacket() {}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">Reference to the client this packet came from</param>
|
/// <param name="client">Reference to the client this packet came from</param>
|
||||||
/// <param name="packet">Packet data</param>
|
/// <param name="packet">Packet data</param>
|
||||||
|
|
|
@ -47,6 +47,7 @@ using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
||||||
|
using RegionFlags = OpenMetaverse.RegionFlags;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -346,7 +347,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private int m_moneyBalance;
|
private int m_moneyBalance;
|
||||||
private int m_animationSequenceNumber = 1;
|
private int m_animationSequenceNumber = 1;
|
||||||
private bool m_SendLogoutPacketWhenClosing = true;
|
private bool m_SendLogoutPacketWhenClosing = true;
|
||||||
private AgentUpdateArgs lastarg;
|
|
||||||
|
/// <summary>
|
||||||
|
/// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
|
||||||
|
/// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
|
||||||
|
/// is doing absolutely nothing.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
|
||||||
|
/// cannot retain a reference to it outside of that method.
|
||||||
|
/// </remarks>
|
||||||
|
private AgentUpdateArgs m_lastAgentUpdateArgs;
|
||||||
|
|
||||||
protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
|
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
|
protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
|
||||||
|
@ -3921,7 +3932,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
|
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
|
||||||
|
|
||||||
ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
|
ImprovedTerseObjectUpdatePacket packet
|
||||||
|
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
|
||||||
|
|
||||||
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
||||||
packet.RegionData.TimeDilation = timeDilation;
|
packet.RegionData.TimeDilation = timeDilation;
|
||||||
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
|
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
|
||||||
|
@ -3966,7 +3979,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
|
List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
|
||||||
|
|
||||||
ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
|
ImprovedTerseObjectUpdatePacket packet
|
||||||
|
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
|
||||||
|
PacketType.ImprovedTerseObjectUpdate);
|
||||||
|
|
||||||
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
||||||
packet.RegionData.TimeDilation = timeDilation;
|
packet.RegionData.TimeDilation = timeDilation;
|
||||||
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
|
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
|
||||||
|
@ -4958,7 +4974,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
|
Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
|
||||||
Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
|
Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
|
||||||
|
|
||||||
ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
|
ImprovedTerseObjectUpdatePacket.ObjectDataBlock block
|
||||||
|
= PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
|
||||||
|
|
||||||
block.Data = data;
|
block.Data = data;
|
||||||
|
|
||||||
if (textureEntry != null && textureEntry.Length > 0)
|
if (textureEntry != null && textureEntry.Length > 0)
|
||||||
|
@ -5190,7 +5208,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
protected virtual void RegisterLocalPacketHandlers()
|
protected virtual void RegisterLocalPacketHandlers()
|
||||||
{
|
{
|
||||||
AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
|
AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
|
||||||
|
|
||||||
|
// If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
|
||||||
|
// for each AgentUpdate packet.
|
||||||
AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
|
AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
|
||||||
|
|
||||||
AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
|
AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
|
||||||
AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
|
AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
|
||||||
AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
|
AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
|
||||||
|
@ -5417,80 +5439,83 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
#region Scene/Avatar
|
#region Scene/Avatar
|
||||||
|
|
||||||
private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
|
private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
|
||||||
{
|
{
|
||||||
if (OnAgentUpdate != null)
|
if (OnAgentUpdate != null)
|
||||||
{
|
{
|
||||||
bool update = false;
|
AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
|
||||||
AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
|
|
||||||
|
|
||||||
#region Packet Session and User Check
|
#region Packet Session and User Check
|
||||||
if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId)
|
if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId)
|
||||||
|
{
|
||||||
|
PacketPool.Instance.ReturnPacket(packet);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
|
bool update = false;
|
||||||
|
AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
|
||||||
|
|
||||||
// We can only check when we have something to check
|
if (m_lastAgentUpdateArgs != null)
|
||||||
// against.
|
|
||||||
|
|
||||||
if (lastarg != null)
|
|
||||||
{
|
{
|
||||||
|
// These should be ordered from most-likely to
|
||||||
|
// least likely to change. I've made an initial
|
||||||
|
// guess at that.
|
||||||
update =
|
update =
|
||||||
(
|
(
|
||||||
(x.BodyRotation != lastarg.BodyRotation) ||
|
(x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) ||
|
||||||
(x.CameraAtAxis != lastarg.CameraAtAxis) ||
|
(x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) ||
|
||||||
(x.CameraCenter != lastarg.CameraCenter) ||
|
(x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
|
||||||
(x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
|
(x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
|
||||||
(x.CameraUpAxis != lastarg.CameraUpAxis) ||
|
(x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
|
||||||
(x.ControlFlags != lastarg.ControlFlags) ||
|
(x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
|
||||||
(x.Far != lastarg.Far) ||
|
(x.Far != m_lastAgentUpdateArgs.Far) ||
|
||||||
(x.Flags != lastarg.Flags) ||
|
(x.Flags != m_lastAgentUpdateArgs.Flags) ||
|
||||||
(x.State != lastarg.State) ||
|
(x.State != m_lastAgentUpdateArgs.State) ||
|
||||||
(x.HeadRotation != lastarg.HeadRotation) ||
|
(x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
|
||||||
(x.SessionID != lastarg.SessionID) ||
|
(x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
|
||||||
(x.AgentID != lastarg.AgentID)
|
(x.AgentID != m_lastAgentUpdateArgs.AgentID)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
m_lastAgentUpdateArgs = new AgentUpdateArgs();
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These should be ordered from most-likely to
|
|
||||||
// least likely to change. I've made an initial
|
|
||||||
// guess at that.
|
|
||||||
|
|
||||||
if (update)
|
if (update)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
|
// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
|
||||||
|
|
||||||
AgentUpdateArgs arg = new AgentUpdateArgs();
|
m_lastAgentUpdateArgs.AgentID = x.AgentID;
|
||||||
arg.AgentID = x.AgentID;
|
m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation;
|
||||||
arg.BodyRotation = x.BodyRotation;
|
m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
|
||||||
arg.CameraAtAxis = x.CameraAtAxis;
|
m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter;
|
||||||
arg.CameraCenter = x.CameraCenter;
|
m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
|
||||||
arg.CameraLeftAxis = x.CameraLeftAxis;
|
m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
|
||||||
arg.CameraUpAxis = x.CameraUpAxis;
|
m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags;
|
||||||
arg.ControlFlags = x.ControlFlags;
|
m_lastAgentUpdateArgs.Far = x.Far;
|
||||||
arg.Far = x.Far;
|
m_lastAgentUpdateArgs.Flags = x.Flags;
|
||||||
arg.Flags = x.Flags;
|
m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
|
||||||
arg.HeadRotation = x.HeadRotation;
|
m_lastAgentUpdateArgs.SessionID = x.SessionID;
|
||||||
arg.SessionID = x.SessionID;
|
m_lastAgentUpdateArgs.State = x.State;
|
||||||
arg.State = x.State;
|
|
||||||
UpdateAgent handlerAgentUpdate = OnAgentUpdate;
|
UpdateAgent handlerAgentUpdate = OnAgentUpdate;
|
||||||
UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
|
UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
|
||||||
lastarg = arg; // save this set of arguments for nexttime
|
|
||||||
if (handlerPreAgentUpdate != null)
|
if (handlerPreAgentUpdate != null)
|
||||||
OnPreAgentUpdate(this, arg);
|
OnPreAgentUpdate(this, m_lastAgentUpdateArgs);
|
||||||
|
|
||||||
if (handlerAgentUpdate != null)
|
if (handlerAgentUpdate != null)
|
||||||
OnAgentUpdate(this, arg);
|
OnAgentUpdate(this, m_lastAgentUpdateArgs);
|
||||||
|
|
||||||
handlerAgentUpdate = null;
|
handlerAgentUpdate = null;
|
||||||
handlerPreAgentUpdate = null;
|
handlerPreAgentUpdate = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketPool.Instance.ReturnPacket(packet);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5862,7 +5887,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
msgpack.MessageBlock.ID,
|
msgpack.MessageBlock.ID,
|
||||||
msgpack.MessageBlock.Offline != 0 ? true : false,
|
msgpack.MessageBlock.Offline != 0 ? true : false,
|
||||||
msgpack.MessageBlock.Position,
|
msgpack.MessageBlock.Position,
|
||||||
msgpack.MessageBlock.BinaryBucket);
|
msgpack.MessageBlock.BinaryBucket,
|
||||||
|
true);
|
||||||
|
|
||||||
handlerInstantMessage(this, im);
|
handlerInstantMessage(this, im);
|
||||||
}
|
}
|
||||||
|
@ -9054,7 +9080,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
switch (Utils.BytesToString(messagePacket.MethodData.Method))
|
string method = Utils.BytesToString(messagePacket.MethodData.Method);
|
||||||
|
|
||||||
|
switch (method)
|
||||||
{
|
{
|
||||||
case "getinfo":
|
case "getinfo":
|
||||||
if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
|
if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
|
||||||
|
@ -9370,7 +9398,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket);
|
m_log.WarnFormat(
|
||||||
|
"[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}",
|
||||||
|
method, Name, Scene.Name);
|
||||||
|
|
||||||
|
for (int i = 0; i < messagePacket.ParamList.Length; i++)
|
||||||
|
{
|
||||||
|
EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i];
|
||||||
|
string data = (string)Utils.BytesToString(block.Parameter);
|
||||||
|
m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11756,7 +11794,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
logPacket = false;
|
logPacket = false;
|
||||||
|
|
||||||
if (DebugPacketLevel <= 50
|
if (DebugPacketLevel <= 50
|
||||||
& (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
|
&& (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
|
||||||
logPacket = false;
|
logPacket = false;
|
||||||
|
|
||||||
if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
|
if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
|
||||||
|
@ -11830,8 +11868,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (!ProcessPacketMethod(packet))
|
if (!ProcessPacketMethod(packet))
|
||||||
m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
|
m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
|
||||||
|
|
||||||
PacketPool.Instance.ReturnPacket(packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
|
private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
|
||||||
|
@ -12284,7 +12320,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
|
ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
|
||||||
ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
|
ImprovedTerseObjectUpdatePacket packet
|
||||||
|
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
|
||||||
|
PacketType.ImprovedTerseObjectUpdate);
|
||||||
|
|
||||||
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
|
||||||
packet.RegionData.TimeDilation = timeDilation;
|
packet.RegionData.TimeDilation = timeDilation;
|
||||||
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
|
packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
|
||||||
|
|
|
@ -37,6 +37,7 @@ using log4net;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenMetaverse.Packets;
|
using OpenMetaverse.Packets;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Framework.Monitoring;
|
using OpenSim.Framework.Monitoring;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
@ -100,9 +101,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
/// <summary>The measured resolution of Environment.TickCount</summary>
|
/// <summary>The measured resolution of Environment.TickCount</summary>
|
||||||
public readonly float TickCountResolution;
|
public readonly float TickCountResolution;
|
||||||
|
|
||||||
/// <summary>Number of prim updates to put on the queue each time the
|
/// <summary>Number of prim updates to put on the queue each time the
|
||||||
/// OnQueueEmpty event is triggered for updates</summary>
|
/// OnQueueEmpty event is triggered for updates</summary>
|
||||||
public readonly int PrimUpdatesPerCallback;
|
public readonly int PrimUpdatesPerCallback;
|
||||||
|
|
||||||
/// <summary>Number of texture packets to put on the queue each time the
|
/// <summary>Number of texture packets to put on the queue each time the
|
||||||
/// OnQueueEmpty event is triggered for textures</summary>
|
/// OnQueueEmpty event is triggered for textures</summary>
|
||||||
public readonly int TextureSendLimit;
|
public readonly int TextureSendLimit;
|
||||||
|
@ -111,6 +114,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
//PacketEventDictionary packetEvents = new PacketEventDictionary();
|
//PacketEventDictionary packetEvents = new PacketEventDictionary();
|
||||||
/// <summary>Incoming packets that are awaiting handling</summary>
|
/// <summary>Incoming packets that are awaiting handling</summary>
|
||||||
private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
|
private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
|
||||||
|
|
||||||
/// <summary></summary>
|
/// <summary></summary>
|
||||||
//private UDPClientCollection m_clients = new UDPClientCollection();
|
//private UDPClientCollection m_clients = new UDPClientCollection();
|
||||||
/// <summary>Bandwidth throttle for this UDP server</summary>
|
/// <summary>Bandwidth throttle for this UDP server</summary>
|
||||||
|
@ -121,28 +125,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
/// <summary>Manages authentication for agent circuits</summary>
|
/// <summary>Manages authentication for agent circuits</summary>
|
||||||
private AgentCircuitManager m_circuitManager;
|
private AgentCircuitManager m_circuitManager;
|
||||||
|
|
||||||
/// <summary>Reference to the scene this UDP server is attached to</summary>
|
/// <summary>Reference to the scene this UDP server is attached to</summary>
|
||||||
protected Scene m_scene;
|
protected Scene m_scene;
|
||||||
|
|
||||||
/// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
|
/// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
|
||||||
private Location m_location;
|
private Location m_location;
|
||||||
|
|
||||||
/// <summary>The size of the receive buffer for the UDP socket. This value
|
/// <summary>The size of the receive buffer for the UDP socket. This value
|
||||||
/// is passed up to the operating system and used in the system networking
|
/// is passed up to the operating system and used in the system networking
|
||||||
/// stack. Use zero to leave this value as the default</summary>
|
/// stack. Use zero to leave this value as the default</summary>
|
||||||
private int m_recvBufferSize;
|
private int m_recvBufferSize;
|
||||||
|
|
||||||
/// <summary>Flag to process packets asynchronously or synchronously</summary>
|
/// <summary>Flag to process packets asynchronously or synchronously</summary>
|
||||||
private bool m_asyncPacketHandling;
|
private bool m_asyncPacketHandling;
|
||||||
|
|
||||||
/// <summary>Tracks whether or not a packet was sent each round so we know
|
/// <summary>Tracks whether or not a packet was sent each round so we know
|
||||||
/// whether or not to sleep</summary>
|
/// whether or not to sleep</summary>
|
||||||
private bool m_packetSent;
|
private bool m_packetSent;
|
||||||
|
|
||||||
/// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
|
/// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
|
||||||
private int m_elapsedMSSinceLastStatReport = 0;
|
private int m_elapsedMSSinceLastStatReport = 0;
|
||||||
|
|
||||||
/// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
|
/// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
|
||||||
private int m_tickLastOutgoingPacketHandler;
|
private int m_tickLastOutgoingPacketHandler;
|
||||||
|
|
||||||
/// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
|
/// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
|
||||||
private int m_elapsedMSOutgoingPacketHandler;
|
private int m_elapsedMSOutgoingPacketHandler;
|
||||||
|
|
||||||
/// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
|
/// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
|
||||||
private int m_elapsed100MSOutgoingPacketHandler;
|
private int m_elapsed100MSOutgoingPacketHandler;
|
||||||
|
|
||||||
/// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
|
/// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
|
||||||
private int m_elapsed500MSOutgoingPacketHandler;
|
private int m_elapsed500MSOutgoingPacketHandler;
|
||||||
|
|
||||||
|
@ -155,6 +168,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>Flag to signal when clients should send pings</summary>
|
/// <summary>Flag to signal when clients should send pings</summary>
|
||||||
protected bool m_sendPing;
|
protected bool m_sendPing;
|
||||||
|
|
||||||
|
private Pool<IncomingPacket> m_incomingPacketPool;
|
||||||
|
|
||||||
private int m_defaultRTO = 0;
|
private int m_defaultRTO = 0;
|
||||||
private int m_maxRTO = 0;
|
private int m_maxRTO = 0;
|
||||||
private int m_ackTimeout = 0;
|
private int m_ackTimeout = 0;
|
||||||
|
@ -175,7 +190,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IClientAPI m_currentIncomingClient;
|
private IClientAPI m_currentIncomingClient;
|
||||||
|
|
||||||
public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
|
public LLUDPServer(
|
||||||
|
IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
|
||||||
|
IConfigSource configSource, AgentCircuitManager circuitManager)
|
||||||
: base(listenIP, (int)port)
|
: base(listenIP, (int)port)
|
||||||
{
|
{
|
||||||
#region Environment.TickCount Measurement
|
#region Environment.TickCount Measurement
|
||||||
|
@ -222,6 +239,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_pausedAckTimeout = 1000 * 300; // 5 minutes
|
m_pausedAckTimeout = 1000 * 300; // 5 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: This actually only needs to be done once since the PacketPool is shared across all servers.
|
||||||
|
// However, there is no harm in temporarily doing it multiple times.
|
||||||
|
IConfig packetConfig = configSource.Configs["PacketPool"];
|
||||||
|
if (packetConfig != null)
|
||||||
|
{
|
||||||
|
PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
|
||||||
|
PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
|
||||||
|
UsePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", false);
|
||||||
|
}
|
||||||
|
|
||||||
#region BinaryStats
|
#region BinaryStats
|
||||||
config = configSource.Configs["Statistics.Binary"];
|
config = configSource.Configs["Statistics.Binary"];
|
||||||
m_shouldCollectStats = false;
|
m_shouldCollectStats = false;
|
||||||
|
@ -249,20 +276,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
m_throttle = new TokenBucket(null, sceneThrottleBps);
|
m_throttle = new TokenBucket(null, sceneThrottleBps);
|
||||||
ThrottleRates = new ThrottleRates(configSource);
|
ThrottleRates = new ThrottleRates(configSource);
|
||||||
|
|
||||||
|
if (UsePools)
|
||||||
|
m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if (m_scene == null)
|
StartInbound();
|
||||||
throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
|
StartOutbound();
|
||||||
|
|
||||||
|
m_elapsedMSSinceLastStatReport = Environment.TickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartInbound()
|
||||||
|
{
|
||||||
m_log.InfoFormat(
|
m_log.InfoFormat(
|
||||||
"[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
|
"[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}",
|
||||||
m_asyncPacketHandling ? "asynchronous" : "synchronous");
|
m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools);
|
||||||
|
|
||||||
base.Start(m_recvBufferSize, m_asyncPacketHandling);
|
base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
|
||||||
|
|
||||||
// Start the packet processing threads
|
// This thread will process the packets received that are placed on the packetInbox
|
||||||
Watchdog.StartThread(
|
Watchdog.StartThread(
|
||||||
IncomingPacketHandler,
|
IncomingPacketHandler,
|
||||||
string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
|
string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
|
||||||
|
@ -271,6 +306,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
true,
|
true,
|
||||||
GetWatchdogIncomingAlarmData,
|
GetWatchdogIncomingAlarmData,
|
||||||
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
|
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private new void StartOutbound()
|
||||||
|
{
|
||||||
|
m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
|
||||||
|
|
||||||
|
base.StartOutbound();
|
||||||
|
|
||||||
Watchdog.StartThread(
|
Watchdog.StartThread(
|
||||||
OutgoingPacketHandler,
|
OutgoingPacketHandler,
|
||||||
|
@ -280,8 +322,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
true,
|
true,
|
||||||
GetWatchdogOutgoingAlarmData,
|
GetWatchdogOutgoingAlarmData,
|
||||||
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
|
Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
m_elapsedMSSinceLastStatReport = Environment.TickCount;
|
public void Stop()
|
||||||
|
{
|
||||||
|
m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
|
||||||
|
base.StopOutbound();
|
||||||
|
base.StopInbound();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -306,12 +353,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
|
m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void Stop()
|
|
||||||
{
|
|
||||||
m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
|
|
||||||
base.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddScene(IScene scene)
|
public void AddScene(IScene scene)
|
||||||
{
|
{
|
||||||
if (m_scene != null)
|
if (m_scene != null)
|
||||||
|
@ -328,6 +369,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
m_scene = (Scene)scene;
|
m_scene = (Scene)scene;
|
||||||
m_location = new Location(m_scene.RegionInfo.RegionHandle);
|
m_location = new Location(m_scene.RegionInfo.RegionHandle);
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"debug lludp start",
|
||||||
|
"debug lludp start <in|out|all>",
|
||||||
|
"Control LLUDP packet processing.",
|
||||||
|
"No effect if packet processing has already started.\n"
|
||||||
|
+ "in - start inbound processing.\n"
|
||||||
|
+ "out - start outbound processing.\n"
|
||||||
|
+ "all - start in and outbound processing.\n",
|
||||||
|
HandleStartCommand);
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"debug lludp stop",
|
||||||
|
"debug lludp stop <in|out|all>",
|
||||||
|
"Stop LLUDP packet processing.",
|
||||||
|
"No effect if packet processing has already stopped.\n"
|
||||||
|
+ "in - stop inbound processing.\n"
|
||||||
|
+ "out - stop outbound processing.\n"
|
||||||
|
+ "all - stop in and outbound processing.\n",
|
||||||
|
HandleStopCommand);
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"debug lludp status",
|
||||||
|
"debug lludp status",
|
||||||
|
"Return status of LLUDP packet processing.",
|
||||||
|
HandleStatusCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleStartCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length != 4)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string subCommand = args[3];
|
||||||
|
|
||||||
|
if (subCommand == "in" || subCommand == "all")
|
||||||
|
StartInbound();
|
||||||
|
|
||||||
|
if (subCommand == "out" || subCommand == "all")
|
||||||
|
StartOutbound();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleStopCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length != 4)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string subCommand = args[3];
|
||||||
|
|
||||||
|
if (subCommand == "in" || subCommand == "all")
|
||||||
|
StopInbound();
|
||||||
|
|
||||||
|
if (subCommand == "out" || subCommand == "all")
|
||||||
|
StopOutbound();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleStatusCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HandlesRegion(Location x)
|
public bool HandlesRegion(Location x)
|
||||||
|
@ -411,6 +527,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
byte[] data = packet.ToBytes();
|
byte[] data = packet.ToBytes();
|
||||||
SendPacketData(udpClient, data, packet.Type, category, method);
|
SendPacketData(udpClient, data, packet.Type, category, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketPool.Instance.ReturnPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -695,7 +813,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
LLUDPClient udpClient = null;
|
LLUDPClient udpClient = null;
|
||||||
Packet packet = null;
|
Packet packet = null;
|
||||||
int packetEnd = buffer.DataLength - 1;
|
int packetEnd = buffer.DataLength - 1;
|
||||||
IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
|
IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;
|
||||||
|
|
||||||
#region Decoding
|
#region Decoding
|
||||||
|
|
||||||
|
@ -705,7 +823,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
|
// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
|
||||||
// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
return; // Drop undersizd packet
|
return; // Drop undersized packet
|
||||||
}
|
}
|
||||||
|
|
||||||
int headerLen = 7;
|
int headerLen = 7;
|
||||||
|
@ -728,7 +846,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
|
// packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
|
||||||
|
// // Only allocate a buffer for zerodecoding if the packet is zerocoded
|
||||||
|
// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
|
||||||
|
// If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
|
||||||
|
// assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
|
||||||
|
// bytes are copied out).
|
||||||
|
packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
|
||||||
// Only allocate a buffer for zerodecoding if the packet is zerocoded
|
// Only allocate a buffer for zerodecoding if the packet is zerocoded
|
||||||
((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
|
((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
|
||||||
}
|
}
|
||||||
|
@ -743,11 +867,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
return; // Drop short packet
|
return; // Drop short packet
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (m_malformedCount < 100)
|
if (m_malformedCount < 100)
|
||||||
m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
|
m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
|
||||||
|
|
||||||
m_malformedCount++;
|
m_malformedCount++;
|
||||||
|
|
||||||
if ((m_malformedCount % 100000) == 0)
|
if ((m_malformedCount % 100000) == 0)
|
||||||
m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
|
m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
|
||||||
}
|
}
|
||||||
|
@ -768,7 +894,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// UseCircuitCode handling
|
// UseCircuitCode handling
|
||||||
if (packet.Type == PacketType.UseCircuitCode)
|
if (packet.Type == PacketType.UseCircuitCode)
|
||||||
{
|
{
|
||||||
object[] array = new object[] { buffer, packet };
|
// We need to copy the endpoint so that it doesn't get changed when another thread reuses the
|
||||||
|
// buffer.
|
||||||
|
object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
|
||||||
|
|
||||||
Util.FireAndForget(HandleUseCircuitCode, array);
|
Util.FireAndForget(HandleUseCircuitCode, array);
|
||||||
|
|
||||||
|
@ -777,7 +905,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
// Determine which agent this packet came from
|
// Determine which agent this packet came from
|
||||||
IClientAPI client;
|
IClientAPI client;
|
||||||
if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView))
|
if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
|
||||||
{
|
{
|
||||||
//m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
|
//m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
|
||||||
return;
|
return;
|
||||||
|
@ -801,6 +929,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// Handle appended ACKs
|
// Handle appended ACKs
|
||||||
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
|
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
|
||||||
|
// packet.Header.AckList.Length, client.Name, m_scene.Name);
|
||||||
|
|
||||||
for (int i = 0; i < packet.Header.AckList.Length; i++)
|
for (int i = 0; i < packet.Header.AckList.Length; i++)
|
||||||
udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
|
udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
|
||||||
}
|
}
|
||||||
|
@ -810,6 +942,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
PacketAckPacket ackPacket = (PacketAckPacket)packet;
|
PacketAckPacket ackPacket = (PacketAckPacket)packet;
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
|
||||||
|
// ackPacket.Packets.Length, client.Name, m_scene.Name);
|
||||||
|
|
||||||
for (int i = 0; i < ackPacket.Packets.Length; i++)
|
for (int i = 0; i < ackPacket.Packets.Length; i++)
|
||||||
udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
|
udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
|
||||||
|
|
||||||
|
@ -823,6 +959,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (packet.Header.Reliable)
|
if (packet.Header.Reliable)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}",
|
||||||
|
// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name);
|
||||||
|
|
||||||
udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
|
udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
|
||||||
|
|
||||||
// This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
|
// This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
|
||||||
|
@ -869,6 +1009,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (packet.Type == PacketType.StartPingCheck)
|
if (packet.Type == PacketType.StartPingCheck)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
|
||||||
|
|
||||||
// We don't need to do anything else with ping checks
|
// We don't need to do anything else with ping checks
|
||||||
StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
|
StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
|
||||||
CompletePing(udpClient, startPing.PingID.PingID);
|
CompletePing(udpClient, startPing.PingID.PingID);
|
||||||
|
@ -888,8 +1030,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
#endregion Ping Check Handling
|
#endregion Ping Check Handling
|
||||||
|
|
||||||
|
IncomingPacket incomingPacket;
|
||||||
|
|
||||||
// Inbox insertion
|
// Inbox insertion
|
||||||
packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
|
if (UsePools)
|
||||||
|
{
|
||||||
|
incomingPacket = m_incomingPacketPool.GetObject();
|
||||||
|
incomingPacket.Client = (LLClientView)client;
|
||||||
|
incomingPacket.Packet = packet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
incomingPacket = new IncomingPacket((LLClientView)client, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
packetInbox.Enqueue(incomingPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region BinaryStats
|
#region BinaryStats
|
||||||
|
@ -975,21 +1130,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private void HandleUseCircuitCode(object o)
|
private void HandleUseCircuitCode(object o)
|
||||||
{
|
{
|
||||||
IPEndPoint remoteEndPoint = null;
|
IPEndPoint endPoint = null;
|
||||||
IClientAPI client = null;
|
IClientAPI client = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// DateTime startTime = DateTime.Now;
|
// DateTime startTime = DateTime.Now;
|
||||||
object[] array = (object[])o;
|
object[] array = (object[])o;
|
||||||
UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
|
endPoint = (IPEndPoint)array[0];
|
||||||
UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
|
UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
|
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
|
||||||
uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
|
uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint);
|
||||||
|
|
||||||
remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
|
|
||||||
|
|
||||||
AuthenticateResponse sessionInfo;
|
AuthenticateResponse sessionInfo;
|
||||||
if (IsClientAuthorized(uccp, out sessionInfo))
|
if (IsClientAuthorized(uccp, out sessionInfo))
|
||||||
|
@ -1000,13 +1153,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
uccp.CircuitCode.Code,
|
uccp.CircuitCode.Code,
|
||||||
uccp.CircuitCode.ID,
|
uccp.CircuitCode.ID,
|
||||||
uccp.CircuitCode.SessionID,
|
uccp.CircuitCode.SessionID,
|
||||||
remoteEndPoint,
|
endPoint,
|
||||||
sessionInfo);
|
sessionInfo);
|
||||||
|
|
||||||
// Send ack straight away to let the viewer know that the connection is active.
|
// Send ack straight away to let the viewer know that the connection is active.
|
||||||
// The client will be null if it already exists (e.g. if on a region crossing the client sends a use
|
// The client will be null if it already exists (e.g. if on a region crossing the client sends a use
|
||||||
// circuit code to the existing child agent. This is not particularly obvious.
|
// circuit code to the existing child agent. This is not particularly obvious.
|
||||||
SendAckImmediate(remoteEndPoint, uccp.Header.Sequence);
|
SendAckImmediate(endPoint, uccp.Header.Sequence);
|
||||||
|
|
||||||
// We only want to send initial data to new clients, not ones which are being converted from child to root.
|
// We only want to send initial data to new clients, not ones which are being converted from child to root.
|
||||||
if (client != null)
|
if (client != null)
|
||||||
|
@ -1017,7 +1170,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// Don't create clients for unauthorized requesters.
|
// Don't create clients for unauthorized requesters.
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
|
"[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
|
||||||
uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
|
uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
|
@ -1029,7 +1182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
m_log.ErrorFormat(
|
||||||
"[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
|
"[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
|
||||||
remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a",
|
endPoint != null ? endPoint.ToString() : "n/a",
|
||||||
client != null ? client.Name : "unknown",
|
client != null ? client.Name : "unknown",
|
||||||
client != null ? client.AgentId.ToString() : "unknown",
|
client != null ? client.AgentId.ToString() : "unknown",
|
||||||
e.Message,
|
e.Message,
|
||||||
|
@ -1094,9 +1247,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
IClientAPI client = null;
|
IClientAPI client = null;
|
||||||
|
|
||||||
// In priciple there shouldn't be more than one thread here, ever.
|
// We currently synchronize this code across the whole scene to avoid issues such as
|
||||||
// But in case that happens, we need to synchronize this piece of code
|
// http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
|
||||||
// because it's too important
|
// consistently, this lock could probably be removed.
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (!m_scene.TryGetClient(agentID, out client))
|
if (!m_scene.TryGetClient(agentID, out client))
|
||||||
|
@ -1146,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// on to en-US to avoid number parsing issues
|
// on to en-US to avoid number parsing issues
|
||||||
Culture.SetCurrentCulture();
|
Culture.SetCurrentCulture();
|
||||||
|
|
||||||
while (base.IsRunning)
|
while (IsRunningInbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -1161,7 +1314,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packetInbox.Dequeue(100, ref incomingPacket))
|
if (packetInbox.Dequeue(100, ref incomingPacket))
|
||||||
|
{
|
||||||
ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
|
ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
|
||||||
|
|
||||||
|
if (UsePools)
|
||||||
|
m_incomingPacketPool.ReturnObject(incomingPacket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -1188,7 +1346,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// Action generic every round
|
// Action generic every round
|
||||||
Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
|
Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
|
||||||
|
|
||||||
while (base.IsRunning)
|
while (base.IsRunningOutbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,6 +30,7 @@ using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
namespace OpenMetaverse
|
namespace OpenMetaverse
|
||||||
{
|
{
|
||||||
|
@ -58,17 +59,29 @@ namespace OpenMetaverse
|
||||||
/// <summary>Flag to process packets asynchronously or synchronously</summary>
|
/// <summary>Flag to process packets asynchronously or synchronously</summary>
|
||||||
private bool m_asyncPacketHandling;
|
private bool m_asyncPacketHandling;
|
||||||
|
|
||||||
/// <summary>The all important shutdown flag</summary>
|
/// <summary>
|
||||||
private volatile bool m_shutdownFlag = true;
|
/// Pool to use for handling data. May be null if UsePools = false;
|
||||||
|
/// </summary>
|
||||||
|
protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool;
|
||||||
|
|
||||||
/// <summary>Returns true if the server is currently listening, otherwise false</summary>
|
/// <summary>
|
||||||
public bool IsRunning { get { return !m_shutdownFlag; } }
|
/// Are we to use object pool(s) to reduce memory churn when receiving data?
|
||||||
|
/// </summary>
|
||||||
|
public bool UsePools { get; protected set; }
|
||||||
|
|
||||||
|
/// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
|
||||||
|
public bool IsRunningInbound { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary>
|
||||||
|
/// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks>
|
||||||
|
public bool IsRunningOutbound { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bindAddress">Local IP address to bind the server to</param>
|
/// <param name="bindAddress">Local IP address to bind the server to</param>
|
||||||
/// <param name="port">Port to listening for incoming UDP packets on</param>
|
/// <param name="port">Port to listening for incoming UDP packets on</param>
|
||||||
|
/// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param>
|
||||||
public OpenSimUDPBase(IPAddress bindAddress, int port)
|
public OpenSimUDPBase(IPAddress bindAddress, int port)
|
||||||
{
|
{
|
||||||
m_localBindAddress = bindAddress;
|
m_localBindAddress = bindAddress;
|
||||||
|
@ -76,7 +89,7 @@ namespace OpenMetaverse
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start the UDP server
|
/// Start inbound UDP packet handling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="recvBufferSize">The size of the receive buffer for
|
/// <param name="recvBufferSize">The size of the receive buffer for
|
||||||
/// the UDP socket. This value is passed up to the operating system
|
/// the UDP socket. This value is passed up to the operating system
|
||||||
|
@ -91,11 +104,16 @@ namespace OpenMetaverse
|
||||||
/// manner (not throwing an exception when the remote side resets the
|
/// manner (not throwing an exception when the remote side resets the
|
||||||
/// connection). This call is ignored on Mono where the flag is not
|
/// connection). This call is ignored on Mono where the flag is not
|
||||||
/// necessary</remarks>
|
/// necessary</remarks>
|
||||||
public void Start(int recvBufferSize, bool asyncPacketHandling)
|
public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
|
||||||
{
|
{
|
||||||
|
if (UsePools)
|
||||||
|
m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
|
||||||
|
else
|
||||||
|
m_pool = null;
|
||||||
|
|
||||||
m_asyncPacketHandling = asyncPacketHandling;
|
m_asyncPacketHandling = asyncPacketHandling;
|
||||||
|
|
||||||
if (m_shutdownFlag)
|
if (!IsRunningInbound)
|
||||||
{
|
{
|
||||||
const int SIO_UDP_CONNRESET = -1744830452;
|
const int SIO_UDP_CONNRESET = -1744830452;
|
||||||
|
|
||||||
|
@ -127,8 +145,7 @@ namespace OpenMetaverse
|
||||||
|
|
||||||
m_udpSocket.Bind(ipep);
|
m_udpSocket.Bind(ipep);
|
||||||
|
|
||||||
// we're not shutting down, we're starting up
|
IsRunningInbound = true;
|
||||||
m_shutdownFlag = false;
|
|
||||||
|
|
||||||
// kick off an async receive. The Start() method will return, the
|
// kick off an async receive. The Start() method will return, the
|
||||||
// actual receives will occur asynchronously and will be caught in
|
// actual receives will occur asynchronously and will be caught in
|
||||||
|
@ -138,28 +155,41 @@ namespace OpenMetaverse
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops the UDP server
|
/// Start outbound UDP packet handling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Stop()
|
public void StartOutbound()
|
||||||
{
|
{
|
||||||
if (!m_shutdownFlag)
|
IsRunningOutbound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopInbound()
|
||||||
|
{
|
||||||
|
if (IsRunningInbound)
|
||||||
{
|
{
|
||||||
// wait indefinitely for a writer lock. Once this is called, the .NET runtime
|
// wait indefinitely for a writer lock. Once this is called, the .NET runtime
|
||||||
// will deny any more reader locks, in effect blocking all other send/receive
|
// will deny any more reader locks, in effect blocking all other send/receive
|
||||||
// threads. Once we have the lock, we set shutdownFlag to inform the other
|
// threads. Once we have the lock, we set IsRunningInbound = false to inform the other
|
||||||
// threads that the socket is closed.
|
// threads that the socket is closed.
|
||||||
m_shutdownFlag = true;
|
IsRunningInbound = false;
|
||||||
m_udpSocket.Close();
|
m_udpSocket.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void StopOutbound()
|
||||||
|
{
|
||||||
|
IsRunningOutbound = false;
|
||||||
|
}
|
||||||
|
|
||||||
private void AsyncBeginReceive()
|
private void AsyncBeginReceive()
|
||||||
{
|
{
|
||||||
// allocate a packet buffer
|
UDPPacketBuffer buf;
|
||||||
//WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
|
|
||||||
UDPPacketBuffer buf = new UDPPacketBuffer();
|
|
||||||
|
|
||||||
if (!m_shutdownFlag)
|
if (UsePools)
|
||||||
|
buf = m_pool.GetObject();
|
||||||
|
else
|
||||||
|
buf = new UDPPacketBuffer();
|
||||||
|
|
||||||
|
if (IsRunningInbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -212,7 +242,7 @@ namespace OpenMetaverse
|
||||||
{
|
{
|
||||||
// Asynchronous receive operations will complete here through the call
|
// Asynchronous receive operations will complete here through the call
|
||||||
// to AsyncBeginReceive
|
// to AsyncBeginReceive
|
||||||
if (!m_shutdownFlag)
|
if (IsRunningInbound)
|
||||||
{
|
{
|
||||||
// Asynchronous mode will start another receive before the
|
// Asynchronous mode will start another receive before the
|
||||||
// callback for this packet is even fired. Very parallel :-)
|
// callback for this packet is even fired. Very parallel :-)
|
||||||
|
@ -221,8 +251,6 @@ namespace OpenMetaverse
|
||||||
|
|
||||||
// get the buffer that was created in AsyncBeginReceive
|
// get the buffer that was created in AsyncBeginReceive
|
||||||
// this is the received data
|
// this is the received data
|
||||||
//WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
|
|
||||||
//UDPPacketBuffer buffer = wrappedBuffer.Instance;
|
|
||||||
UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
|
UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -239,7 +267,8 @@ namespace OpenMetaverse
|
||||||
catch (ObjectDisposedException) { }
|
catch (ObjectDisposedException) { }
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
//wrappedBuffer.Dispose();
|
if (UsePools)
|
||||||
|
m_pool.ReturnObject(buffer);
|
||||||
|
|
||||||
// Synchronous mode waits until the packet callback completes
|
// Synchronous mode waits until the packet callback completes
|
||||||
// before starting the receive to fetch another packet
|
// before starting the receive to fetch another packet
|
||||||
|
@ -252,7 +281,7 @@ namespace OpenMetaverse
|
||||||
|
|
||||||
public void AsyncBeginSend(UDPPacketBuffer buf)
|
public void AsyncBeginSend(UDPPacketBuffer buf)
|
||||||
{
|
{
|
||||||
if (!m_shutdownFlag)
|
if (IsRunningOutbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,10 +31,10 @@ using System.Reflection;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.Packets;
|
using OpenMetaverse.Packets;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
|
|
||||||
namespace OpenSim.Framework
|
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
|
|
||||||
public sealed class PacketPool
|
public sealed class PacketPool
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
@ -44,14 +44,28 @@ namespace OpenSim.Framework
|
||||||
private bool packetPoolEnabled = true;
|
private bool packetPoolEnabled = true;
|
||||||
private bool dataBlockPoolEnabled = true;
|
private bool dataBlockPoolEnabled = true;
|
||||||
|
|
||||||
|
private PercentageStat m_packetsReusedStat = new PercentageStat(
|
||||||
|
"PacketsReused",
|
||||||
|
"Packets reused",
|
||||||
|
"clientstack",
|
||||||
|
"packetpool",
|
||||||
|
StatVerbosity.Debug,
|
||||||
|
"Number of packets reused out of all requests to the packet pool");
|
||||||
|
|
||||||
|
private PercentageStat m_blocksReusedStat = new PercentageStat(
|
||||||
|
"BlocksReused",
|
||||||
|
"Blocks reused",
|
||||||
|
"clientstack",
|
||||||
|
"packetpool",
|
||||||
|
StatVerbosity.Debug,
|
||||||
|
"Number of data blocks reused out of all requests to the packet pool");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pool of packets available for reuse.
|
||||||
|
/// </summary>
|
||||||
private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
|
private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
|
||||||
|
|
||||||
private static Dictionary<Type, Stack<Object>> DataBlocks =
|
private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>();
|
||||||
new Dictionary<Type, Stack<Object>>();
|
|
||||||
|
|
||||||
static PacketPool()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PacketPool Instance
|
public static PacketPool Instance
|
||||||
{
|
{
|
||||||
|
@ -70,8 +84,21 @@ namespace OpenSim.Framework
|
||||||
get { return dataBlockPoolEnabled; }
|
get { return dataBlockPoolEnabled; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PacketPool()
|
||||||
|
{
|
||||||
|
StatsManager.RegisterStat(m_packetsReusedStat);
|
||||||
|
StatsManager.RegisterStat(m_blocksReusedStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a packet of the given type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='type'></param>
|
||||||
|
/// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns>
|
||||||
public Packet GetPacket(PacketType type)
|
public Packet GetPacket(PacketType type)
|
||||||
{
|
{
|
||||||
|
m_packetsReusedStat.Consequent++;
|
||||||
|
|
||||||
Packet packet;
|
Packet packet;
|
||||||
|
|
||||||
if (!packetPoolEnabled)
|
if (!packetPoolEnabled)
|
||||||
|
@ -81,13 +108,19 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
|
if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type);
|
||||||
|
|
||||||
// Creating a new packet if we cannot reuse an old package
|
// Creating a new packet if we cannot reuse an old package
|
||||||
packet = Packet.BuildPacket(type);
|
packet = Packet.BuildPacket(type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type);
|
||||||
|
|
||||||
// Recycle old packages
|
// Recycle old packages
|
||||||
packet = (pool[type]).Pop();
|
m_packetsReusedStat.Antecedent++;
|
||||||
|
|
||||||
|
packet = pool[type].Pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +169,7 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
PacketType type = GetType(bytes);
|
PacketType type = GetType(bytes);
|
||||||
|
|
||||||
Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
|
// Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Packet packet = GetPacket(type);
|
Packet packet = GetPacket(type);
|
||||||
|
@ -183,6 +216,7 @@ namespace OpenSim.Framework
|
||||||
switch (packet.Type)
|
switch (packet.Type)
|
||||||
{
|
{
|
||||||
// List pooling packets here
|
// List pooling packets here
|
||||||
|
case PacketType.AgentUpdate:
|
||||||
case PacketType.PacketAck:
|
case PacketType.PacketAck:
|
||||||
case PacketType.ObjectUpdate:
|
case PacketType.ObjectUpdate:
|
||||||
case PacketType.ImprovedTerseObjectUpdate:
|
case PacketType.ImprovedTerseObjectUpdate:
|
||||||
|
@ -197,7 +231,9 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
if ((pool[type]).Count < 50)
|
if ((pool[type]).Count < 50)
|
||||||
{
|
{
|
||||||
(pool[type]).Push(packet);
|
// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type);
|
||||||
|
|
||||||
|
pool[type].Push(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -209,16 +245,21 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T GetDataBlock<T>() where T: new()
|
public T GetDataBlock<T>() where T: new()
|
||||||
{
|
{
|
||||||
lock (DataBlocks)
|
lock (DataBlocks)
|
||||||
{
|
{
|
||||||
|
m_blocksReusedStat.Consequent++;
|
||||||
|
|
||||||
Stack<Object> s;
|
Stack<Object> s;
|
||||||
|
|
||||||
if (DataBlocks.TryGetValue(typeof(T), out s))
|
if (DataBlocks.TryGetValue(typeof(T), out s))
|
||||||
{
|
{
|
||||||
if (s.Count > 0)
|
if (s.Count > 0)
|
||||||
|
{
|
||||||
|
m_blocksReusedStat.Antecedent++;
|
||||||
return (T)s.Pop();
|
return (T)s.Pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -229,7 +270,7 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ReturnDataBlock<T>(T block) where T: new()
|
public void ReturnDataBlock<T>(T block) where T: new()
|
||||||
{
|
{
|
||||||
if (block == null)
|
if (block == null)
|
||||||
return;
|
return;
|
|
@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
/// This will contain basic tests for the LindenUDP client stack
|
/// This will contain basic tests for the LindenUDP client stack
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class BasicCircuitTests
|
public class BasicCircuitTests : OpenSimTestCase
|
||||||
{
|
{
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private TestLLUDPServer m_udpServer;
|
private TestLLUDPServer m_udpServer;
|
||||||
|
@ -65,8 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public override void SetUp()
|
||||||
{
|
{
|
||||||
|
base.SetUp();
|
||||||
m_scene = new SceneHelpers().SetupScene();
|
m_scene = new SceneHelpers().SetupScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
public void TestAddClient()
|
public void TestAddClient()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// XmlConfigurator.Configure();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
AddUdpServer();
|
AddUdpServer();
|
||||||
|
|
||||||
|
|
|
@ -406,6 +406,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
|
public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
|
||||||
|
{
|
||||||
|
DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
|
||||||
{
|
{
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
|
@ -448,7 +453,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
so.FromItemID = UUID.Zero;
|
so.FromItemID = UUID.Zero;
|
||||||
|
|
||||||
SceneObjectPart rootPart = so.RootPart;
|
SceneObjectPart rootPart = so.RootPart;
|
||||||
so.AbsolutePosition = sp.AbsolutePosition;
|
so.AbsolutePosition = absolutePos;
|
||||||
|
if (absoluteRot != Quaternion.Identity)
|
||||||
|
{
|
||||||
|
so.UpdateGroupRotationR(absoluteRot);
|
||||||
|
}
|
||||||
so.AttachedAvatar = UUID.Zero;
|
so.AttachedAvatar = UUID.Zero;
|
||||||
rootPart.SetParentLocalId(0);
|
rootPart.SetParentLocalId(0);
|
||||||
so.ClearPartAttachmentData();
|
so.ClearPartAttachmentData();
|
||||||
|
|
|
@ -525,7 +525,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
{
|
{
|
||||||
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
|
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < appearance.Wearables[j].Count; j++)
|
for (int j = 0; j < appearance.Wearables[i].Count; j++)
|
||||||
{
|
{
|
||||||
if (appearance.Wearables[i][j].ItemID == UUID.Zero)
|
if (appearance.Wearables[i][j].ItemID == UUID.Zero)
|
||||||
continue;
|
continue;
|
||||||
|
@ -533,6 +533,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
// Ignore ruth's assets
|
// Ignore ruth's assets
|
||||||
if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
|
if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
|
InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
|
||||||
baseItem = invService.GetItem(baseItem);
|
baseItem = invService.GetItem(baseItem);
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
client.FirstName+" "+client.LastName,
|
client.FirstName+" "+client.LastName,
|
||||||
destID, (byte)211, false,
|
destID, (byte)211, false,
|
||||||
String.Empty,
|
String.Empty,
|
||||||
transactionID, false, new Vector3(), new byte[0]),
|
transactionID, false, new Vector3(), new byte[0], true),
|
||||||
delegate(bool success) {} );
|
delegate(bool success) {} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,74 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name>
|
||||||
|
// to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis
|
||||||
|
// of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously
|
||||||
|
// done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here.
|
||||||
|
else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
|
||||||
|
{
|
||||||
|
UUID destinationFolderID = UUID.Zero;
|
||||||
|
|
||||||
|
if (im.binaryBucket != null && im.binaryBucket.Length >= 16)
|
||||||
|
{
|
||||||
|
destinationFolderID = new UUID(im.binaryBucket, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destinationFolderID != UUID.Zero)
|
||||||
|
{
|
||||||
|
InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
|
||||||
|
if (destinationFolder == null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
|
||||||
|
client.Name, scene.Name, destinationFolderID);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IInventoryService invService = scene.InventoryService;
|
||||||
|
|
||||||
|
UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
|
||||||
|
|
||||||
|
InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
|
||||||
|
item = invService.GetItem(item);
|
||||||
|
InventoryFolderBase folder = null;
|
||||||
|
UUID? previousParentFolderID = null;
|
||||||
|
|
||||||
|
if (item != null) // It's an item
|
||||||
|
{
|
||||||
|
previousParentFolderID = item.Folder;
|
||||||
|
item.Folder = destinationFolderID;
|
||||||
|
|
||||||
|
invService.DeleteItems(item.Owner, new List<UUID>() { item.ID });
|
||||||
|
scene.AddInventoryItem(client, item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
folder = new InventoryFolderBase(inventoryID, client.AgentId);
|
||||||
|
folder = invService.GetFolder(folder);
|
||||||
|
|
||||||
|
if (folder != null) // It's a folder
|
||||||
|
{
|
||||||
|
previousParentFolderID = folder.ParentID;
|
||||||
|
folder.ParentID = destinationFolderID;
|
||||||
|
invService.MoveFolder(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
|
||||||
|
if (previousParentFolderID != null)
|
||||||
|
{
|
||||||
|
InventoryFolderBase previousParentFolder
|
||||||
|
= new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
|
||||||
|
previousParentFolder = invService.GetFolder(previousParentFolder);
|
||||||
|
scene.SendInventoryUpdate(client, previousParentFolder, true, true);
|
||||||
|
|
||||||
|
scene.SendInventoryUpdate(client, destinationFolder, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (
|
else if (
|
||||||
im.dialog == (byte)InstantMessageDialog.InventoryDeclined
|
im.dialog == (byte)InstantMessageDialog.InventoryDeclined
|
||||||
|| im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
|
|| im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
|
||||||
|
@ -315,9 +383,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
|
||||||
InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
|
InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
|
||||||
item = invService.GetItem(item);
|
item = invService.GetItem(item);
|
||||||
InventoryFolderBase folder = null;
|
InventoryFolderBase folder = null;
|
||||||
|
UUID? previousParentFolderID = null;
|
||||||
|
|
||||||
if (item != null && trashFolder != null)
|
if (item != null && trashFolder != null)
|
||||||
{
|
{
|
||||||
|
previousParentFolderID = item.Folder;
|
||||||
item.Folder = trashFolder.ID;
|
item.Folder = trashFolder.ID;
|
||||||
|
|
||||||
// Diva comment: can't we just update this item???
|
// Diva comment: can't we just update this item???
|
||||||
|
@ -333,6 +403,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
|
||||||
|
|
||||||
if (folder != null & trashFolder != null)
|
if (folder != null & trashFolder != null)
|
||||||
{
|
{
|
||||||
|
previousParentFolderID = folder.ParentID;
|
||||||
folder.ParentID = trashFolder.ID;
|
folder.ParentID = trashFolder.ID;
|
||||||
invService.MoveFolder(folder);
|
invService.MoveFolder(folder);
|
||||||
}
|
}
|
||||||
|
@ -352,6 +423,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
|
||||||
client.SendAgentAlertMessage("Unable to delete "+
|
client.SendAgentAlertMessage("Unable to delete "+
|
||||||
"received inventory" + reason, false);
|
"received inventory" + reason, false);
|
||||||
}
|
}
|
||||||
|
// Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
|
||||||
|
else if (previousParentFolderID != null)
|
||||||
|
{
|
||||||
|
InventoryFolderBase previousParentFolder
|
||||||
|
= new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
|
||||||
|
previousParentFolder = invService.GetFolder(previousParentFolder);
|
||||||
|
scene.SendInventoryUpdate(client, previousParentFolder, true, true);
|
||||||
|
|
||||||
|
scene.SendInventoryUpdate(client, trashFolder, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
|
ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||||
client.FirstName+" "+client.LastName, targetid,
|
client.FirstName+" "+client.LastName, targetid,
|
||||||
(byte)InstantMessageDialog.RequestTeleport, false,
|
(byte)InstantMessageDialog.RequestTeleport, false,
|
||||||
message, sessionID, false, presence.AbsolutePosition,
|
message, sessionID, false, presence.AbsolutePosition,
|
||||||
new Byte[0]);
|
new Byte[0], true);
|
||||||
m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
|
m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
|
||||||
|
|
||||||
m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
|
m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
|
||||||
|
|
|
@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||||
client.FirstName+" "+client.LastName, targetid,
|
client.FirstName+" "+client.LastName, targetid,
|
||||||
(byte)InstantMessageDialog.RequestTeleport, false,
|
(byte)InstantMessageDialog.RequestTeleport, false,
|
||||||
message, dest, false, presence.AbsolutePosition,
|
message, dest, false, presence.AbsolutePosition,
|
||||||
new Byte[0]);
|
new Byte[0], true);
|
||||||
|
|
||||||
if (m_TransferModule != null)
|
if (m_TransferModule != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -486,6 +486,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
if (sp.ParentID != (uint)0)
|
if (sp.ParentID != (uint)0)
|
||||||
sp.StandUp();
|
sp.StandUp();
|
||||||
|
|
||||||
|
// At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
|
||||||
|
// the viewer. However, it might mean that the viewer does not see the black teleport screen (untested).
|
||||||
sp.ControllingClient.SendTeleportStart(teleportFlags);
|
sp.ControllingClient.SendTeleportStart(teleportFlags);
|
||||||
|
|
||||||
// the avatar.Close below will clear the child region list. We need this below for (possibly)
|
// the avatar.Close below will clear the child region list. We need this below for (possibly)
|
||||||
|
@ -561,8 +563,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
// So let's wait
|
// So let's wait
|
||||||
Thread.Sleep(200);
|
Thread.Sleep(200);
|
||||||
|
|
||||||
|
// At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
|
||||||
|
// unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
|
||||||
|
// only on TeleportFinish). This is untested for region teleport between different simulators
|
||||||
|
// though this probably also works.
|
||||||
m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
|
m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1068,6 +1073,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
Scene initiatingScene)
|
Scene initiatingScene)
|
||||||
{
|
{
|
||||||
Thread.Sleep(10000);
|
Thread.Sleep(10000);
|
||||||
|
|
||||||
IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
|
IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
if (im != null)
|
if (im != null)
|
||||||
{
|
{
|
||||||
|
@ -1080,11 +1086,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
(uint)(int)position.X,
|
(uint)(int)position.X,
|
||||||
(uint)(int)position.Y,
|
(uint)(int)position.Y,
|
||||||
(uint)(int)position.Z);
|
(uint)(int)position.Z);
|
||||||
GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero,
|
|
||||||
"Region", agent.UUID,
|
GridInstantMessage m
|
||||||
(byte)InstantMessageDialog.GodLikeRequestTeleport, false,
|
= new GridInstantMessage(
|
||||||
"", gotoLocation, false, new Vector3(127, 0, 0),
|
initiatingScene,
|
||||||
new Byte[0]);
|
UUID.Zero,
|
||||||
|
"Region",
|
||||||
|
agent.UUID,
|
||||||
|
(byte)InstantMessageDialog.GodLikeRequestTeleport,
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
gotoLocation,
|
||||||
|
false,
|
||||||
|
new Vector3(127, 0, 0),
|
||||||
|
new Byte[0],
|
||||||
|
false);
|
||||||
|
|
||||||
im.SendInstantMessage(m, delegate(bool success)
|
im.SendInstantMessage(m, delegate(bool success)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
|
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
|
||||||
|
|
|
@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
|
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
|
||||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
|
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
|
||||||
|
|
||||||
if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
|
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
|
||||||
GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
|
GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
|
||||||
|
@ -232,7 +232,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
||||||
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -256,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
reason = string.Empty;
|
reason = string.Empty;
|
||||||
logout = false;
|
logout = false;
|
||||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
||||||
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
|
||||||
{
|
{
|
||||||
// this user is going to another grid
|
// this user is going to another grid
|
||||||
// check if HyperGrid teleport is allowed, based on user level
|
// check if HyperGrid teleport is allowed, based on user level
|
||||||
|
@ -298,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
// The rest is only needed for controlling appearance
|
// The rest is only needed for controlling appearance
|
||||||
|
|
||||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
||||||
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
|
||||||
{
|
{
|
||||||
// this user is going to another grid
|
// this user is going to another grid
|
||||||
if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID))
|
if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID))
|
||||||
|
|
|
@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
|
||||||
{
|
{
|
||||||
foreach (IMonitor monitor in m_staticMonitors)
|
foreach (IMonitor monitor in m_staticMonitors)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"[MONITOR MODULE]: {0} reports {1} = {2}",
|
"[MONITOR MODULE]: {0} reports {1} = {2}",
|
||||||
m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
|
m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
|
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
|
||||||
{
|
{
|
||||||
m_log.InfoFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"[MONITOR MODULE]: {0} reports {1} = {2}",
|
"[MONITOR MODULE]: {0} reports {1} = {2}",
|
||||||
m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
|
m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,15 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||||
Write(String.Format(line, args));
|
Write(String.Format(line, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
if (!Enabled) return;
|
||||||
|
if (m_logFile != null)
|
||||||
|
{
|
||||||
|
m_logFile.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Write(string line)
|
public void Write(string line)
|
||||||
{
|
{
|
||||||
if (!Enabled) return;
|
if (!Enabled) return;
|
||||||
|
|
|
@ -31,6 +31,7 @@ using System.Reflection;
|
||||||
|
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Region.ClientStack.LindenUDP;
|
||||||
using OpenSim.Region.Framework;
|
using OpenSim.Region.Framework;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||||
{
|
{
|
||||||
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
|
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private const int ALL_SIDES = -1;
|
private const int ALL_SIDES = -1;
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
|
|
||||||
foreach (DearchiveContext sceneContext in sceneContexts.Values)
|
foreach (DearchiveContext sceneContext in sceneContexts.Values)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[ARCHIVER:] Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
|
m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
if (!m_merge)
|
if (!m_merge)
|
||||||
{
|
{
|
||||||
|
@ -324,7 +324,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||||
Util.FireAndForget(delegate(object o)
|
Util.FireAndForget(delegate(object o)
|
||||||
{
|
{
|
||||||
Thread.Sleep(15000);
|
Thread.Sleep(15000);
|
||||||
m_log.Info("Starting scripts in scene objects");
|
m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
|
||||||
|
|
||||||
foreach (DearchiveContext sceneContext in sceneContexts.Values)
|
foreach (DearchiveContext sceneContext in sceneContexts.Values)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,7 @@ using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using RegionFlags = OpenMetaverse.RegionFlags;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.World.Estate
|
namespace OpenSim.Region.CoreModules.World.Estate
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,7 @@ using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using RegionFlags = OpenMetaverse.RegionFlags;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.World.Land
|
namespace OpenSim.Region.CoreModules.World.Land
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
@ -83,46 +84,99 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects", false, "delete object owner",
|
"Objects", false, "delete object owner",
|
||||||
"delete object owner <UUID>",
|
"delete object owner <UUID>",
|
||||||
"Delete a scene object by owner", HandleDeleteObject);
|
"Delete scene objects by owner",
|
||||||
|
"Command will ask for confirmation before proceeding.",
|
||||||
|
HandleDeleteObject);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects", false, "delete object creator",
|
"Objects", false, "delete object creator",
|
||||||
"delete object creator <UUID>",
|
"delete object creator <UUID>",
|
||||||
"Delete a scene object by creator", HandleDeleteObject);
|
"Delete scene objects by creator",
|
||||||
|
"Command will ask for confirmation before proceeding.",
|
||||||
|
HandleDeleteObject);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects", false, "delete object uuid",
|
"Objects", false, "delete object uuid",
|
||||||
"delete object uuid <UUID>",
|
"delete object uuid <UUID>",
|
||||||
"Delete a scene object by uuid", HandleDeleteObject);
|
"Delete a scene object by uuid",
|
||||||
|
HandleDeleteObject);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects", false, "delete object name",
|
"Objects", false, "delete object name",
|
||||||
"delete object name [--regex] <name>",
|
"delete object name [--regex] <name>",
|
||||||
"Delete a scene object by name.",
|
"Delete a scene object by name.",
|
||||||
"If --regex is specified then the name is treatead as a regular expression",
|
"Command will ask for confirmation before proceeding.\n"
|
||||||
|
+ "If --regex is specified then the name is treatead as a regular expression",
|
||||||
HandleDeleteObject);
|
HandleDeleteObject);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects", false, "delete object outside",
|
"Objects", false, "delete object outside",
|
||||||
"delete object outside",
|
"delete object outside",
|
||||||
"Delete all scene objects outside region boundaries", HandleDeleteObject);
|
"Delete all scene objects outside region boundaries",
|
||||||
|
"Command will ask for confirmation before proceeding.",
|
||||||
|
HandleDeleteObject);
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand(
|
||||||
|
"Objects",
|
||||||
|
false,
|
||||||
|
"delete object pos",
|
||||||
|
"delete object pos <start-coord> to <end-coord>",
|
||||||
|
"Delete scene objects within the given area.",
|
||||||
|
"Each component of the coord is comma separated. There must be no spaces between the commas.\n"
|
||||||
|
+ "If you don't care about the z component you can simply omit it.\n"
|
||||||
|
+ "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n"
|
||||||
|
+ "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n"
|
||||||
|
+ "If you want to specify the minimum value of a component then you can use -~ instead of a number\n"
|
||||||
|
+ "e.g.\n"
|
||||||
|
+ "delete object pos 20,20,20 to 40,40,40\n"
|
||||||
|
+ "delete object pos 20,20 to 40,40\n"
|
||||||
|
+ "delete object pos ,20,20 to ,40,40\n"
|
||||||
|
+ "delete object pos ,,30 to ,,~\n"
|
||||||
|
+ "delete object pos ,,-~ to ,,30",
|
||||||
|
HandleDeleteObject);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects",
|
"Objects",
|
||||||
false,
|
false,
|
||||||
"show object uuid",
|
"show object uuid",
|
||||||
"show object uuid <UUID>",
|
"show object uuid [--full] <UUID>",
|
||||||
"Show details of a scene object with the given UUID", HandleShowObjectByUuid);
|
"Show details of a scene object with the given UUID",
|
||||||
|
"The --full option will print out information on all the parts of the object.\n"
|
||||||
|
+ "For yet more detailed part information, use the \"show part\" commands.",
|
||||||
|
HandleShowObjectByUuid);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects",
|
"Objects",
|
||||||
false,
|
false,
|
||||||
"show object name",
|
"show object name",
|
||||||
"show object name [--regex] <name>",
|
"show object name [--full] [--regex] <name>",
|
||||||
"Show details of scene objects with the given name.",
|
"Show details of scene objects with the given name.",
|
||||||
"If --regex is specified then the name is treatead as a regular expression",
|
"The --full option will print out information on all the parts of the object.\n"
|
||||||
|
+ "For yet more detailed part information, use the \"show part\" commands.\n"
|
||||||
|
+ "If --regex is specified then the name is treatead as a regular expression.",
|
||||||
HandleShowObjectByName);
|
HandleShowObjectByName);
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand(
|
||||||
|
"Objects",
|
||||||
|
false,
|
||||||
|
"show object pos",
|
||||||
|
"show object pos [--full] <start-coord> to <end-coord>",
|
||||||
|
"Show details of scene objects within the given area.",
|
||||||
|
"The --full option will print out information on all the parts of the object.\n"
|
||||||
|
+ "For yet more detailed part information, use the \"show part\" commands.\n"
|
||||||
|
+ "Each component of the coord is comma separated. There must be no spaces between the commas.\n"
|
||||||
|
+ "If you don't care about the z component you can simply omit it.\n"
|
||||||
|
+ "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n"
|
||||||
|
+ "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n"
|
||||||
|
+ "If you want to specify the minimum value of a component then you can use -~ instead of a number\n"
|
||||||
|
+ "e.g.\n"
|
||||||
|
+ "show object pos 20,20,20 to 40,40,40\n"
|
||||||
|
+ "show object pos 20,20 to 40,40\n"
|
||||||
|
+ "show object pos ,20,20 to ,40,40\n"
|
||||||
|
+ "show object pos ,,30 to ,,~\n"
|
||||||
|
+ "show object pos ,,-~ to ,,30",
|
||||||
|
HandleShowObjectByPos);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"Objects",
|
"Objects",
|
||||||
false,
|
false,
|
||||||
|
@ -138,6 +192,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
"Show details of scene object parts with the given name.",
|
"Show details of scene object parts with the given name.",
|
||||||
"If --regex is specified then the name is treatead as a regular expression",
|
"If --regex is specified then the name is treatead as a regular expression",
|
||||||
HandleShowPartByName);
|
HandleShowPartByName);
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand(
|
||||||
|
"Objects",
|
||||||
|
false,
|
||||||
|
"show part pos",
|
||||||
|
"show part pos <start-coord> to <end-coord>",
|
||||||
|
"Show details of scene object parts within the given area.",
|
||||||
|
"Each component of the coord is comma separated. There must be no spaces between the commas.\n"
|
||||||
|
+ "If you don't care about the z component you can simply omit it.\n"
|
||||||
|
+ "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n"
|
||||||
|
+ "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n"
|
||||||
|
+ "If you want to specify the minimum value of a component then you can use -~ instead of a number\n"
|
||||||
|
+ "e.g.\n"
|
||||||
|
+ "show object pos 20,20,20 to 40,40,40\n"
|
||||||
|
+ "show object pos 20,20 to 40,40\n"
|
||||||
|
+ "show object pos ,20,20 to ,40,40\n"
|
||||||
|
+ "show object pos ,,30 to ,,~\n"
|
||||||
|
+ "show object pos ,,-~ to ,,30",
|
||||||
|
HandleShowPartByPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
|
@ -150,21 +223,68 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
|
// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleShowObjectByUuid(string module, string[] cmd)
|
/// <summary>
|
||||||
|
/// Outputs the sogs to console.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='searchPredicate'></param>
|
||||||
|
/// <param name='showFull'>If true then output all part details. If false then output summary.</param>
|
||||||
|
private void OutputSogsToConsole(Predicate<SceneObjectGroup> searchPredicate, bool showFull)
|
||||||
|
{
|
||||||
|
List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (SceneObjectGroup so in sceneObjects)
|
||||||
|
{
|
||||||
|
AddSceneObjectReport(sb, so, showFull);
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name);
|
||||||
|
|
||||||
|
m_console.OutputFormat(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OutputSopsToConsole(Predicate<SceneObjectPart> searchPredicate, bool showFull)
|
||||||
|
{
|
||||||
|
List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
|
||||||
|
List<SceneObjectPart> parts = new List<SceneObjectPart>();
|
||||||
|
|
||||||
|
sceneObjects.ForEach(so => parts.AddRange(Array.FindAll<SceneObjectPart>(so.Parts, searchPredicate)));
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (SceneObjectPart part in parts)
|
||||||
|
{
|
||||||
|
AddScenePartReport(sb, part, showFull);
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name);
|
||||||
|
|
||||||
|
m_console.OutputFormat(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleShowObjectByUuid(string module, string[] cmdparams)
|
||||||
{
|
{
|
||||||
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cmd.Length < 4)
|
bool showFull = false;
|
||||||
|
OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
|
||||||
|
|
||||||
|
List<string> mainParams = options.Parse(cmdparams);
|
||||||
|
|
||||||
|
if (mainParams.Count < 4)
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Usage: show object uuid <uuid>");
|
m_console.OutputFormat("Usage: show object uuid <uuid>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID objectUuid;
|
UUID objectUuid;
|
||||||
if (!UUID.TryParse(cmd[3], out objectUuid))
|
if (!UUID.TryParse(mainParams[3], out objectUuid))
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
|
m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +297,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
AddSceneObjectReport(sb, so);
|
AddSceneObjectReport(sb, so, showFull);
|
||||||
|
|
||||||
m_console.OutputFormat(sb.ToString());
|
m_console.OutputFormat(sb.ToString());
|
||||||
}
|
}
|
||||||
|
@ -187,66 +307,85 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
bool showFull = false;
|
||||||
bool useRegex = false;
|
bool useRegex = false;
|
||||||
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
|
OptionSet options = new OptionSet();
|
||||||
|
options.Add("full", v => showFull = v != null );
|
||||||
|
options.Add("regex", v => useRegex = v != null );
|
||||||
|
|
||||||
List<string> mainParams = options.Parse(cmdparams);
|
List<string> mainParams = options.Parse(cmdparams);
|
||||||
|
|
||||||
if (mainParams.Count < 4)
|
if (mainParams.Count < 4)
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Usage: show object name [--regex] <name>");
|
m_console.OutputFormat("Usage: show object name [--full] [--regex] <name>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string name = mainParams[3];
|
string name = mainParams[3];
|
||||||
|
|
||||||
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
|
Predicate<SceneObjectGroup> searchPredicate;
|
||||||
Action<SceneObjectGroup> searchAction;
|
|
||||||
|
|
||||||
if (useRegex)
|
if (useRegex)
|
||||||
{
|
{
|
||||||
Regex nameRegex = new Regex(name);
|
Regex nameRegex = new Regex(name);
|
||||||
searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }};
|
searchPredicate = so => nameRegex.IsMatch(so.Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }};
|
searchPredicate = so => so.Name == name;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_scene.ForEachSOG(searchAction);
|
OutputSogsToConsole(searchPredicate, showFull);
|
||||||
|
|
||||||
if (sceneObjects.Count == 0)
|
|
||||||
{
|
|
||||||
m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (SceneObjectGroup so in sceneObjects)
|
|
||||||
{
|
|
||||||
AddSceneObjectReport(sb, so);
|
|
||||||
sb.Append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_console.OutputFormat(sb.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleShowPartByUuid(string module, string[] cmd)
|
private void HandleShowObjectByPos(string module, string[] cmdparams)
|
||||||
{
|
{
|
||||||
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cmd.Length < 4)
|
bool showFull = false;
|
||||||
|
OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
|
||||||
|
|
||||||
|
List<string> mainParams = options.Parse(cmdparams);
|
||||||
|
|
||||||
|
if (mainParams.Count < 5)
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Usage: show part uuid <uuid>");
|
m_console.OutputFormat("Usage: show object pos [--full] <start-coord> to <end-coord>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 startVector, endVector;
|
||||||
|
|
||||||
|
if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Predicate<SceneObjectGroup> searchPredicate
|
||||||
|
= so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector);
|
||||||
|
|
||||||
|
OutputSogsToConsole(searchPredicate, showFull);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleShowPartByUuid(string module, string[] cmdparams)
|
||||||
|
{
|
||||||
|
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// bool showFull = false;
|
||||||
|
OptionSet options = new OptionSet();
|
||||||
|
// options.Add("full", v => showFull = v != null );
|
||||||
|
|
||||||
|
List<string> mainParams = options.Parse(cmdparams);
|
||||||
|
|
||||||
|
if (mainParams.Count < 4)
|
||||||
|
{
|
||||||
|
m_console.OutputFormat("Usage: show part uuid [--full] <uuid>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID objectUuid;
|
UUID objectUuid;
|
||||||
if (!UUID.TryParse(cmd[3], out objectUuid))
|
if (!UUID.TryParse(mainParams[3], out objectUuid))
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
|
m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,84 +398,188 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
AddScenePartReport(sb, sop);
|
AddScenePartReport(sb, sop, true);
|
||||||
|
|
||||||
m_console.OutputFormat(sb.ToString());
|
m_console.OutputFormat(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleShowPartByPos(string module, string[] cmdparams)
|
||||||
|
{
|
||||||
|
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// bool showFull = false;
|
||||||
|
OptionSet options = new OptionSet();
|
||||||
|
// options.Add("full", v => showFull = v != null );
|
||||||
|
|
||||||
|
List<string> mainParams = options.Parse(cmdparams);
|
||||||
|
|
||||||
|
if (mainParams.Count < 5)
|
||||||
|
{
|
||||||
|
m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string rawConsoleStartVector = mainParams[3];
|
||||||
|
Vector3 startVector;
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
|
||||||
|
{
|
||||||
|
m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string rawConsoleEndVector = mainParams[5];
|
||||||
|
Vector3 endVector;
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
|
||||||
|
{
|
||||||
|
m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true);
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleShowPartByName(string module, string[] cmdparams)
|
private void HandleShowPartByName(string module, string[] cmdparams)
|
||||||
{
|
{
|
||||||
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// bool showFull = false;
|
||||||
bool useRegex = false;
|
bool useRegex = false;
|
||||||
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
|
OptionSet options = new OptionSet();
|
||||||
|
// options.Add("full", v => showFull = v != null );
|
||||||
|
options.Add("regex", v => useRegex = v != null );
|
||||||
|
|
||||||
List<string> mainParams = options.Parse(cmdparams);
|
List<string> mainParams = options.Parse(cmdparams);
|
||||||
|
|
||||||
if (mainParams.Count < 4)
|
if (mainParams.Count < 4)
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Usage: show part name [--regex] <name>");
|
m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string name = mainParams[3];
|
string name = mainParams[3];
|
||||||
|
|
||||||
List<SceneObjectPart> parts = new List<SceneObjectPart>();
|
Predicate<SceneObjectPart> searchPredicate;
|
||||||
|
|
||||||
Action<SceneObjectGroup> searchAction;
|
|
||||||
|
|
||||||
if (useRegex)
|
if (useRegex)
|
||||||
{
|
{
|
||||||
Regex nameRegex = new Regex(name);
|
Regex nameRegex = new Regex(name);
|
||||||
searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } });
|
searchPredicate = sop => nameRegex.IsMatch(sop.Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } });
|
searchPredicate = sop => sop.Name == name;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_scene.ForEachSOG(searchAction);
|
OutputSopsToConsole(searchPredicate, true);
|
||||||
|
|
||||||
if (parts.Count == 0)
|
|
||||||
{
|
|
||||||
m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (SceneObjectPart part in parts)
|
|
||||||
{
|
|
||||||
AddScenePartReport(sb, part);
|
|
||||||
sb.Append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_console.OutputFormat(sb.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so)
|
/// <summary>
|
||||||
|
/// Append a scene object report to an input StringBuilder
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <param name='sb'></param>
|
||||||
|
/// <param name='so'</param>
|
||||||
|
/// <param name='showFull'>
|
||||||
|
/// If true then information on all parts of an object is appended.
|
||||||
|
/// If false then only summary information about an object is appended.
|
||||||
|
/// </param>
|
||||||
|
private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull)
|
||||||
{
|
{
|
||||||
sb.AppendFormat("Name: {0}\n", so.Name);
|
if (showFull)
|
||||||
sb.AppendFormat("Description: {0}\n", so.Description);
|
{
|
||||||
sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName);
|
foreach (SceneObjectPart sop in so.Parts)
|
||||||
sb.AppendFormat("Parts: {0}\n", so.PrimCount);
|
{
|
||||||
sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags);
|
AddScenePartReport(sb, sop, false);
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddSummarySceneObjectReport(sb, so);
|
||||||
|
}
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop)
|
private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so)
|
||||||
{
|
{
|
||||||
sb.AppendFormat("Name: {0}\n", sop.Name);
|
ConsoleDisplayList cdl = new ConsoleDisplayList();
|
||||||
sb.AppendFormat("Description: {0}\n", sop.Description);
|
cdl.AddRow("Name", so.Name);
|
||||||
sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName);
|
cdl.AddRow("Descrition", so.Description);
|
||||||
sb.AppendFormat("Parent: {0}",
|
cdl.AddRow("Local ID", so.LocalId);
|
||||||
sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID));
|
cdl.AddRow("UUID", so.UUID);
|
||||||
sb.AppendFormat("Link number: {0}\n", sop.LinkNum);
|
cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
|
||||||
sb.AppendFormat("Flags: {0}\n", sop.Flags);
|
cdl.AddRow("Parts", so.PrimCount);
|
||||||
|
cdl.AddRow("Flags", so.RootPart.Flags);
|
||||||
|
|
||||||
return sb;
|
return sb.Append(cdl.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Append a scene object part report to an input StringBuilder
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <param name='sb'></param>
|
||||||
|
/// <param name='sop'</param>
|
||||||
|
/// <param name='showFull'>
|
||||||
|
/// If true then information on each inventory item will be shown.
|
||||||
|
/// If false then only summary inventory information is shown.
|
||||||
|
/// </param>
|
||||||
|
private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull)
|
||||||
|
{
|
||||||
|
ConsoleDisplayList cdl = new ConsoleDisplayList();
|
||||||
|
cdl.AddRow("Name", sop.Name);
|
||||||
|
cdl.AddRow("Description", sop.Description);
|
||||||
|
cdl.AddRow("Local ID", sop.LocalId);
|
||||||
|
cdl.AddRow("UUID", sop.UUID);
|
||||||
|
cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name));
|
||||||
|
cdl.AddRow(
|
||||||
|
"Parent",
|
||||||
|
sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID));
|
||||||
|
cdl.AddRow("Link number", sop.LinkNum);
|
||||||
|
cdl.AddRow("Flags", sop.Flags);
|
||||||
|
|
||||||
|
object itemsOutput;
|
||||||
|
if (showFull)
|
||||||
|
{
|
||||||
|
StringBuilder itemsSb = new StringBuilder("\n");
|
||||||
|
itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
itemsOutput = sop.Inventory.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cdl.AddRow("Items", itemsOutput);
|
||||||
|
|
||||||
|
return sb.Append(cdl.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv)
|
||||||
|
{
|
||||||
|
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||||
|
cdt.Indent = 2;
|
||||||
|
|
||||||
|
cdt.AddColumn("Name", 50);
|
||||||
|
cdt.AddColumn("Type", 12);
|
||||||
|
cdt.AddColumn("Running", 7);
|
||||||
|
cdt.AddColumn("Item UUID", 36);
|
||||||
|
cdt.AddColumn("Asset UUID", 36);
|
||||||
|
|
||||||
|
foreach (TaskInventoryItem item in inv.GetInventoryItems())
|
||||||
|
cdt.AddRow(
|
||||||
|
item.Name,
|
||||||
|
((InventoryType)item.InvType).ToString(),
|
||||||
|
(InventoryType)item.InvType == InventoryType.LSL ? item.ScriptRunning.ToString() : "n/a",
|
||||||
|
item.ItemID.ToString(),
|
||||||
|
item.AssetID.ToString());
|
||||||
|
|
||||||
|
return sb.Append(cdt.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleDeleteObject(string module, string[] cmd)
|
private void HandleDeleteObject(string module, string[] cmd)
|
||||||
|
@ -450,6 +693,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "pos":
|
||||||
|
deletes = GetDeleteCandidatesByPos(module, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
m_console.OutputFormat("Unrecognized mode {0}", mode);
|
m_console.OutputFormat("Unrecognized mode {0}", mode);
|
||||||
return;
|
return;
|
||||||
|
@ -464,7 +711,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
string.Format(
|
string.Format(
|
||||||
"Are you sure that you want to delete {0} objects from {1}",
|
"Are you sure that you want to delete {0} objects from {1}",
|
||||||
deletes.Count, m_scene.RegionInfo.RegionName),
|
deletes.Count, m_scene.RegionInfo.RegionName),
|
||||||
"n");
|
"y/N");
|
||||||
|
|
||||||
if (response.ToLower() != "y")
|
if (response.ToLower() != "y")
|
||||||
{
|
{
|
||||||
|
@ -486,9 +733,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
|
|
||||||
private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
|
private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
|
||||||
{
|
{
|
||||||
if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
bool useRegex = false;
|
bool useRegex = false;
|
||||||
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
|
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
|
||||||
|
|
||||||
|
@ -522,5 +766,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
|
|
||||||
return sceneObjects;
|
return sceneObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get scene object delete candidates by position
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='module'></param>
|
||||||
|
/// <param name='cmdparams'></param>
|
||||||
|
/// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there
|
||||||
|
/// are no objects to delete then the list will be empty./returns>
|
||||||
|
private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams)
|
||||||
|
{
|
||||||
|
if (cmdparams.Length < 5)
|
||||||
|
{
|
||||||
|
m_console.OutputFormat("Usage: delete object pos <start-coord> to <end-coord>");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 startVector, endVector;
|
||||||
|
|
||||||
|
if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return m_scene.GetSceneObjectGroups().FindAll(
|
||||||
|
so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector)
|
||||||
|
{
|
||||||
|
string rawConsoleStartVector = rawComponents.Take(1).Single();
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
|
||||||
|
{
|
||||||
|
m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
|
||||||
|
endVector = Vector3.Zero;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
|
||||||
|
{
|
||||||
|
m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -108,6 +108,15 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// <param name="objectLocalID"></param>
|
/// <param name="objectLocalID"></param>
|
||||||
void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
|
void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Detach the given item to the ground at the specified coordinates & rotation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sp"></param>
|
||||||
|
/// <param name="objectLocalID"></param>
|
||||||
|
/// <param name="absolutePos"></param>
|
||||||
|
/// <param name="absoluteRot"></param>
|
||||||
|
void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Detach the given attachment so that it remains in the user's inventory.
|
/// Detach the given attachment so that it remains in the user's inventory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -267,18 +267,26 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
|
||||||
void ApplyGodPermissions(uint perms);
|
void ApplyGodPermissions(uint perms);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of items in this inventory.
|
||||||
|
/// </summary>
|
||||||
|
int Count { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if this inventory contains any scripts
|
/// Returns true if this inventory contains any scripts
|
||||||
/// </summary></returns>
|
/// </summary></returns>
|
||||||
bool ContainsScripts();
|
bool ContainsScripts();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the count of scripts contained
|
/// Number of scripts in this inventory.
|
||||||
/// </summary></returns>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Includes both running and non running scripts.
|
||||||
|
/// </remarks>
|
||||||
int ScriptCount();
|
int ScriptCount();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the count of running scripts contained
|
/// Number of running scripts in this inventory.
|
||||||
/// </summary></returns>
|
/// </summary></returns>
|
||||||
int RunningScriptCount();
|
int RunningScriptCount();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,31 @@
|
||||||
using System;
|
/*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
||||||
{
|
{
|
||||||
if (m_defaultAnimation.AnimID == animID)
|
if (m_defaultAnimation.AnimID == animID)
|
||||||
{
|
{
|
||||||
ResetDefaultAnimation();
|
m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero);
|
||||||
}
|
}
|
||||||
else if (HasAnimation(animID))
|
else if (HasAnimation(animID))
|
||||||
{
|
{
|
||||||
|
@ -149,19 +149,26 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
||||||
{
|
{
|
||||||
lock (m_animations)
|
lock (m_animations)
|
||||||
{
|
{
|
||||||
animIDs = new UUID[m_animations.Count + 1];
|
int defaultSize = 0;
|
||||||
sequenceNums = new int[m_animations.Count + 1];
|
if (m_defaultAnimation.AnimID != UUID.Zero)
|
||||||
objectIDs = new UUID[m_animations.Count + 1];
|
defaultSize++;
|
||||||
|
|
||||||
animIDs[0] = m_defaultAnimation.AnimID;
|
animIDs = new UUID[m_animations.Count + defaultSize];
|
||||||
sequenceNums[0] = m_defaultAnimation.SequenceNum;
|
sequenceNums = new int[m_animations.Count + defaultSize];
|
||||||
objectIDs[0] = m_defaultAnimation.ObjectID;
|
objectIDs = new UUID[m_animations.Count + defaultSize];
|
||||||
|
|
||||||
|
if (m_defaultAnimation.AnimID != UUID.Zero)
|
||||||
|
{
|
||||||
|
animIDs[0] = m_defaultAnimation.AnimID;
|
||||||
|
sequenceNums[0] = m_defaultAnimation.SequenceNum;
|
||||||
|
objectIDs[0] = m_defaultAnimation.ObjectID;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < m_animations.Count; ++i)
|
for (int i = 0; i < m_animations.Count; ++i)
|
||||||
{
|
{
|
||||||
animIDs[i + 1] = m_animations[i].AnimID;
|
animIDs[i + defaultSize] = m_animations[i].AnimID;
|
||||||
sequenceNums[i + 1] = m_animations[i].SequenceNum;
|
sequenceNums[i + defaultSize] = m_animations[i].SequenceNum;
|
||||||
objectIDs[i + 1] = m_animations[i].ObjectID;
|
objectIDs[i + defaultSize] = m_animations[i].ObjectID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,13 +408,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
|
||||||
{
|
{
|
||||||
lock (m_animations)
|
lock (m_animations)
|
||||||
{
|
{
|
||||||
CurrentMovementAnimation = DetermineMovementAnimation();
|
string newMovementAnimation = DetermineMovementAnimation();
|
||||||
|
if (CurrentMovementAnimation != newMovementAnimation)
|
||||||
|
{
|
||||||
|
CurrentMovementAnimation = DetermineMovementAnimation();
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
|
// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
|
||||||
// CurrentMovementAnimation, m_scenePresence.Name);
|
// CurrentMovementAnimation, m_scenePresence.Name);
|
||||||
|
|
||||||
TrySetMovementAnimation(CurrentMovementAnimation);
|
// Only set it if it's actually changed, give a script
|
||||||
|
// a chance to stop a default animation
|
||||||
|
TrySetMovementAnimation(CurrentMovementAnimation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,13 +121,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This is triggered for both child and root agent client connections.
|
/// This is triggered for both child and root agent client connections.
|
||||||
|
///
|
||||||
/// Triggered before OnClientLogin.
|
/// Triggered before OnClientLogin.
|
||||||
|
///
|
||||||
|
/// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
|
||||||
|
/// do this on a separate thread.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public event OnNewClientDelegate OnNewClient;
|
public event OnNewClientDelegate OnNewClient;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired if the client entering this sim is doing so as a new login
|
/// Fired if the client entering this sim is doing so as a new login
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
|
||||||
|
/// do this on a separate thread.
|
||||||
|
/// </remarks>
|
||||||
public event Action<IClientAPI> OnClientLogin;
|
public event Action<IClientAPI> OnClientLogin;
|
||||||
|
|
||||||
public delegate void OnNewPresenceDelegate(ScenePresence presence);
|
public delegate void OnNewPresenceDelegate(ScenePresence presence);
|
||||||
|
@ -149,6 +157,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
|
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
|
||||||
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
|
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
|
||||||
|
///
|
||||||
|
/// Triggered under per-agent lock. So if you want to perform any long-running operations, please
|
||||||
|
/// do this on a separate thread.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public event OnRemovePresenceDelegate OnRemovePresence;
|
public event OnRemovePresenceDelegate OnRemovePresence;
|
||||||
|
|
||||||
|
@ -425,6 +436,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// At the point of firing, the scene still contains the client's scene presence.
|
/// At the point of firing, the scene still contains the client's scene presence.
|
||||||
|
///
|
||||||
|
/// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
|
||||||
|
/// do this on a separate thread.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public event ClientClosed OnClientClosed;
|
public event ClientClosed OnClientClosed;
|
||||||
|
|
||||||
|
@ -913,7 +927,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
|
public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
|
||||||
public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
|
public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
|
||||||
|
|
||||||
public delegate void SceneObjectPartUpdated(SceneObjectPart sop);
|
public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full);
|
||||||
public event SceneObjectPartUpdated OnSceneObjectPartUpdated;
|
public event SceneObjectPartUpdated OnSceneObjectPartUpdated;
|
||||||
|
|
||||||
public delegate void ScenePresenceUpdated(ScenePresence sp);
|
public delegate void ScenePresenceUpdated(ScenePresence sp);
|
||||||
|
@ -2837,7 +2851,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TriggerSceneObjectPartUpdated(SceneObjectPart sop)
|
public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full)
|
||||||
{
|
{
|
||||||
SceneObjectPartUpdated handler = OnSceneObjectPartUpdated;
|
SceneObjectPartUpdated handler = OnSceneObjectPartUpdated;
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
|
@ -2846,7 +2860,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d(sop);
|
d(sop, full);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1424,7 +1424,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return newFolderID;
|
return newFolderID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems)
|
public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems)
|
||||||
{
|
{
|
||||||
if (folder == null)
|
if (folder == null)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -79,6 +79,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public SynchronizeSceneHandler SynchronizeScene;
|
public SynchronizeSceneHandler SynchronizeScene;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other.
|
||||||
|
/// </summary>
|
||||||
|
private object m_removeClientLock = new object();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Statistical information for this scene.
|
/// Statistical information for this scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -301,6 +306,31 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
private volatile bool m_shuttingDown;
|
private volatile bool m_shuttingDown;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is the scene active?
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If false, maintenance and update loops are not being run. Updates can still be triggered manually if
|
||||||
|
/// the scene is not active.
|
||||||
|
/// </remarks>
|
||||||
|
public bool Active
|
||||||
|
{
|
||||||
|
get { return m_active; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
if (!m_active)
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private volatile bool m_active;
|
||||||
|
|
||||||
// private int m_lastUpdate;
|
// private int m_lastUpdate;
|
||||||
// private bool m_firstHeartbeat = true;
|
// private bool m_firstHeartbeat = true;
|
||||||
|
|
||||||
|
@ -801,13 +831,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
|
SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
|
||||||
TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
|
TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
|
||||||
|
|
||||||
IConfig packetConfig = m_config.Configs["PacketPool"];
|
|
||||||
if (packetConfig != null)
|
|
||||||
{
|
|
||||||
PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
|
|
||||||
PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
|
m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
|
||||||
|
|
||||||
m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
|
m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
|
||||||
|
@ -1161,6 +1184,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void SetSceneCoreDebug(Dictionary<string, string> options)
|
public void SetSceneCoreDebug(Dictionary<string, string> options)
|
||||||
{
|
{
|
||||||
|
if (options.ContainsKey("active"))
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
|
||||||
|
if (bool.TryParse(options["active"], out active))
|
||||||
|
Active = active;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.ContainsKey("scripting"))
|
if (options.ContainsKey("scripting"))
|
||||||
{
|
{
|
||||||
bool enableScripts = true;
|
bool enableScripts = true;
|
||||||
|
@ -1300,6 +1331,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
|
// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
|
||||||
|
|
||||||
//m_heartbeatTimer.Enabled = true;
|
//m_heartbeatTimer.Enabled = true;
|
||||||
|
@ -1341,7 +1374,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
#region Update Methods
|
#region Update Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs per-frame updates regularly
|
/// Activate the various loops necessary to continually update the scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void Heartbeat()
|
private void Heartbeat()
|
||||||
{
|
{
|
||||||
|
@ -1398,7 +1431,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
List<Vector3> coarseLocations;
|
List<Vector3> coarseLocations;
|
||||||
List<UUID> avatarUUIDs;
|
List<UUID> avatarUUIDs;
|
||||||
|
|
||||||
while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun))
|
while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
|
||||||
{
|
{
|
||||||
runtc = Util.EnvironmentTickCount();
|
runtc = Util.EnvironmentTickCount();
|
||||||
++MaintenanceRun;
|
++MaintenanceRun;
|
||||||
|
@ -1457,7 +1490,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
int previousFrameTick, tmpMS;
|
int previousFrameTick, tmpMS;
|
||||||
int maintc = Util.EnvironmentTickCount();
|
int maintc = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
while (!m_shuttingDown && (endFrame == null || Frame < endFrame))
|
while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
|
||||||
{
|
{
|
||||||
++Frame;
|
++Frame;
|
||||||
|
|
||||||
|
@ -2146,7 +2179,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public bool AddRestoredSceneObject(
|
public bool AddRestoredSceneObject(
|
||||||
SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
|
SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
|
||||||
{
|
{
|
||||||
return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
|
if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
|
||||||
|
{
|
||||||
|
EventManager.TriggerObjectAddedToScene(sceneObject);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2709,69 +2749,89 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
|
public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
|
||||||
{
|
{
|
||||||
|
ScenePresence sp;
|
||||||
|
bool vialogin;
|
||||||
|
|
||||||
// Validation occurs in LLUDPServer
|
// Validation occurs in LLUDPServer
|
||||||
|
//
|
||||||
|
// XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
|
||||||
|
// each other. In practice, this does not currently occur in the code.
|
||||||
AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
|
AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
|
||||||
|
|
||||||
bool vialogin
|
// We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection
|
||||||
= (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
|
// and a simultaneous one that removes it (as can happen if the client is closed at a particular point
|
||||||
|| (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
|
// whilst connecting).
|
||||||
|
//
|
||||||
// CheckHeartbeat();
|
// It would be easier to lock across all NewUserConnection(), AddNewClient() and
|
||||||
|
// RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
|
||||||
ScenePresence sp = GetScenePresence(client.AgentId);
|
// response in some module listening to AddNewClient()) from holding up unrelated agent calls.
|
||||||
|
//
|
||||||
// XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
|
// In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
|
||||||
// could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
|
// AddNewClient() operations (though not other ops).
|
||||||
// other problems, and possible the code calling AddNewClient() should ensure that no client is already
|
// In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
|
||||||
// connected.
|
lock (aCircuit)
|
||||||
if (sp == null)
|
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
vialogin
|
||||||
"[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
|
= (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
|
||||||
client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
|
|| (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
|
||||||
|
|
||||||
m_clientManager.Add(client);
|
// CheckHeartbeat();
|
||||||
SubscribeToClientEvents(client);
|
|
||||||
|
|
||||||
sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
|
sp = GetScenePresence(client.AgentId);
|
||||||
m_eventManager.TriggerOnNewPresence(sp);
|
|
||||||
|
|
||||||
sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
|
// XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
|
||||||
|
// could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
|
||||||
// The first agent upon login is a root agent by design.
|
// other problems, and possible the code calling AddNewClient() should ensure that no client is already
|
||||||
// For this agent we will have to rez the attachments.
|
// connected.
|
||||||
// All other AddNewClient calls find aCircuit.child to be true.
|
if (sp == null)
|
||||||
if (aCircuit.child == false)
|
|
||||||
{
|
{
|
||||||
// We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
|
m_log.DebugFormat(
|
||||||
// start the scripts again (since this is done in RezAttachments()).
|
"[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
|
||||||
// XXX: This is convoluted.
|
client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
|
||||||
sp.IsChildAgent = false;
|
|
||||||
|
|
||||||
if (AttachmentsModule != null)
|
m_clientManager.Add(client);
|
||||||
Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
|
SubscribeToClientEvents(client);
|
||||||
|
|
||||||
|
sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
|
||||||
|
m_eventManager.TriggerOnNewPresence(sp);
|
||||||
|
|
||||||
|
sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
|
||||||
|
|
||||||
|
// The first agent upon login is a root agent by design.
|
||||||
|
// For this agent we will have to rez the attachments.
|
||||||
|
// All other AddNewClient calls find aCircuit.child to be true.
|
||||||
|
if (aCircuit.child == false)
|
||||||
|
{
|
||||||
|
// We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
|
||||||
|
// start the scripts again (since this is done in RezAttachments()).
|
||||||
|
// XXX: This is convoluted.
|
||||||
|
sp.IsChildAgent = false;
|
||||||
|
|
||||||
|
if (AttachmentsModule != null)
|
||||||
|
Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
|
||||||
|
sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.WarnFormat(
|
|
||||||
"[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
|
|
||||||
sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
|
// We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
|
||||||
// client is for a root or child agent.
|
// client is for a root or child agent.
|
||||||
client.SceneAgent = sp;
|
client.SceneAgent = sp;
|
||||||
|
|
||||||
|
// Cache the user's name
|
||||||
|
CacheUserName(sp, aCircuit);
|
||||||
|
|
||||||
|
EventManager.TriggerOnNewClient(client);
|
||||||
|
if (vialogin)
|
||||||
|
EventManager.TriggerOnClientLogin(client);
|
||||||
|
}
|
||||||
|
|
||||||
m_LastLogin = Util.EnvironmentTickCount();
|
m_LastLogin = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
// Cache the user's name
|
|
||||||
CacheUserName(sp, aCircuit);
|
|
||||||
|
|
||||||
EventManager.TriggerOnNewClient(client);
|
|
||||||
if (vialogin)
|
|
||||||
EventManager.TriggerOnClientLogin(client);
|
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3300,109 +3360,129 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
// CheckHeartbeat();
|
// CheckHeartbeat();
|
||||||
bool isChildAgent = false;
|
bool isChildAgent = false;
|
||||||
ScenePresence avatar = GetScenePresence(agentID);
|
AgentCircuitData acd;
|
||||||
|
|
||||||
if (avatar == null)
|
lock (m_removeClientLock)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat(
|
acd = m_authenticateHandler.GetAgentCircuitData(agentID);
|
||||||
"[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
|
|
||||||
|
|
||||||
return;
|
if (acd == null)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred
|
||||||
|
// simultaneously.
|
||||||
|
m_authenticateHandler.RemoveCircuit(acd.circuitcode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
lock (acd)
|
||||||
{
|
{
|
||||||
isChildAgent = avatar.IsChildAgent;
|
ScenePresence avatar = GetScenePresence(agentID);
|
||||||
|
|
||||||
m_log.DebugFormat(
|
if (avatar == null)
|
||||||
"[SCENE]: Removing {0} agent {1} {2} from {3}",
|
|
||||||
(isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
|
|
||||||
|
|
||||||
// Don't do this to root agents, it's not nice for the viewer
|
|
||||||
if (closeChildAgents && isChildAgent)
|
|
||||||
{
|
{
|
||||||
// Tell a single agent to disconnect from the region.
|
m_log.WarnFormat(
|
||||||
IEventQueue eq = RequestModuleInterface<IEventQueue>();
|
"[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
|
||||||
if (eq != null)
|
|
||||||
{
|
return;
|
||||||
eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
avatar.ControllingClient.SendShutdownConnectionNotice();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only applies to root agents.
|
|
||||||
if (avatar.ParentID != 0)
|
|
||||||
{
|
|
||||||
avatar.StandUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sceneGraph.removeUserCount(!isChildAgent);
|
|
||||||
|
|
||||||
// TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
|
|
||||||
// unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
|
|
||||||
if (closeChildAgents && CapsModule != null)
|
|
||||||
CapsModule.RemoveCaps(agentID);
|
|
||||||
|
|
||||||
// REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
|
|
||||||
// this method is doing is HORRIBLE!!!
|
|
||||||
avatar.Scene.NeedSceneCacheClear(avatar.UUID);
|
|
||||||
|
|
||||||
if (closeChildAgents && !isChildAgent)
|
|
||||||
{
|
|
||||||
List<ulong> regions = avatar.KnownRegionHandles;
|
|
||||||
regions.Remove(RegionInfo.RegionHandle);
|
|
||||||
m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_eventManager.TriggerClientClosed(agentID, this);
|
|
||||||
m_eventManager.TriggerOnRemovePresence(agentID);
|
|
||||||
|
|
||||||
if (!isChildAgent)
|
|
||||||
{
|
|
||||||
if (AttachmentsModule != null)
|
|
||||||
{
|
|
||||||
AttachmentsModule.DeRezAttachments(avatar);
|
|
||||||
}
|
|
||||||
|
|
||||||
ForEachClient(
|
|
||||||
delegate(IClientAPI client)
|
|
||||||
{
|
|
||||||
//We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
|
|
||||||
try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
|
|
||||||
catch (NullReferenceException) { }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's possible for child agents to have transactions if changes are being made cross-border.
|
|
||||||
if (AgentTransactionsModule != null)
|
|
||||||
AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
|
|
||||||
|
|
||||||
m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.Error(
|
|
||||||
string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Always clean these structures up so that any failure above doesn't cause them to remain in the
|
isChildAgent = avatar.IsChildAgent;
|
||||||
// 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();
|
m_log.DebugFormat(
|
||||||
|
"[SCENE]: Removing {0} agent {1} {2} from {3}",
|
||||||
|
(isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
|
||||||
|
|
||||||
|
// Don't do this to root agents, it's not nice for the viewer
|
||||||
|
if (closeChildAgents && isChildAgent)
|
||||||
|
{
|
||||||
|
// Tell a single agent to disconnect from the region.
|
||||||
|
IEventQueue eq = RequestModuleInterface<IEventQueue>();
|
||||||
|
if (eq != null)
|
||||||
|
{
|
||||||
|
eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
avatar.ControllingClient.SendShutdownConnectionNotice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only applies to root agents.
|
||||||
|
if (avatar.ParentID != 0)
|
||||||
|
{
|
||||||
|
avatar.StandUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sceneGraph.removeUserCount(!isChildAgent);
|
||||||
|
|
||||||
|
// TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
|
||||||
|
// unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
|
||||||
|
if (closeChildAgents && CapsModule != null)
|
||||||
|
CapsModule.RemoveCaps(agentID);
|
||||||
|
|
||||||
|
// REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
|
||||||
|
// this method is doing is HORRIBLE!!!
|
||||||
|
avatar.Scene.NeedSceneCacheClear(avatar.UUID);
|
||||||
|
|
||||||
|
if (closeChildAgents && !isChildAgent)
|
||||||
|
{
|
||||||
|
List<ulong> regions = avatar.KnownRegionHandles;
|
||||||
|
regions.Remove(RegionInfo.RegionHandle);
|
||||||
|
m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_eventManager.TriggerClientClosed(agentID, this);
|
||||||
|
m_eventManager.TriggerOnRemovePresence(agentID);
|
||||||
|
|
||||||
|
if (!isChildAgent)
|
||||||
|
{
|
||||||
|
if (AttachmentsModule != null)
|
||||||
|
{
|
||||||
|
AttachmentsModule.DeRezAttachments(avatar);
|
||||||
|
}
|
||||||
|
|
||||||
|
ForEachClient(
|
||||||
|
delegate(IClientAPI client)
|
||||||
|
{
|
||||||
|
//We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
|
||||||
|
try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
|
||||||
|
catch (NullReferenceException) { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's possible for child agents to have transactions if changes are being made cross-border.
|
||||||
|
if (AgentTransactionsModule != null)
|
||||||
|
AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Error(
|
m_log.Error(
|
||||||
string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
|
string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3461,11 +3541,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Do the work necessary to initiate a new user connection for a particular scene.
|
/// Do the work necessary to initiate a new user connection for a particular scene.
|
||||||
/// At the moment, this consists of setting up the caps infrastructure
|
|
||||||
/// The return bool should allow for connections to be refused, but as not all calling paths
|
|
||||||
/// take proper notice of it let, we allowed banned users in still.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="agent">CircuitData of the agent who is connecting</param>
|
/// <param name="agent">CircuitData of the agent who is connecting</param>
|
||||||
|
/// <param name="teleportFlags"></param>
|
||||||
/// <param name="reason">Outputs the reason for the false response on this string</param>
|
/// <param name="reason">Outputs the reason for the false response on this string</param>
|
||||||
/// <returns>True if the region accepts this agent. False if it does not. False will
|
/// <returns>True if the region accepts this agent. False if it does not. False will
|
||||||
/// also return a reason.</returns>
|
/// also return a reason.</returns>
|
||||||
|
@ -3476,10 +3554,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Do the work necessary to initiate a new user connection for a particular scene.
|
/// Do the work necessary to initiate a new user connection for a particular scene.
|
||||||
/// At the moment, this consists of setting up the caps infrastructure
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The return bool should allow for connections to be refused, but as not all calling paths
|
||||||
|
/// take proper notice of it yet, we still allowed banned users in.
|
||||||
|
///
|
||||||
|
/// At the moment this method consists of setting up the caps infrastructure
|
||||||
/// The return bool should allow for connections to be refused, but as not all calling paths
|
/// The return bool should allow for connections to be refused, but as not all calling paths
|
||||||
/// take proper notice of it let, we allowed banned users in still.
|
/// take proper notice of it let, we allowed banned users in still.
|
||||||
/// </summary>
|
///
|
||||||
|
/// This method is called by the login service (in the case of login) or another simulator (in the case of region
|
||||||
|
/// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection
|
||||||
|
/// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
|
||||||
|
/// the LLUDP stack).
|
||||||
|
/// </remarks>
|
||||||
/// <param name="agent">CircuitData of the agent who is connecting</param>
|
/// <param name="agent">CircuitData of the agent who is connecting</param>
|
||||||
/// <param name="reason">Outputs the reason for the false response on this string</param>
|
/// <param name="reason">Outputs the reason for the false response on this string</param>
|
||||||
/// <param name="requirePresenceLookup">True for normal presence. False for NPC
|
/// <param name="requirePresenceLookup">True for normal presence. False for NPC
|
||||||
|
@ -3566,86 +3654,95 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ILandObject land;
|
||||||
|
|
||||||
ScenePresence sp = GetScenePresence(agent.AgentID);
|
lock (agent)
|
||||||
|
|
||||||
if (sp != null && !sp.IsChildAgent)
|
|
||||||
{
|
{
|
||||||
// We have a zombie from a crashed session.
|
ScenePresence sp = GetScenePresence(agent.AgentID);
|
||||||
// Or the same user is trying to be root twice here, won't work.
|
|
||||||
// Kill it.
|
|
||||||
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(true);
|
if (sp != null && !sp.IsChildAgent)
|
||||||
sp = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
|
|
||||||
|
|
||||||
//On login test land permisions
|
|
||||||
if (vialogin)
|
|
||||||
{
|
|
||||||
if (land != null && !TestLandRestrictions(agent, land, out reason))
|
|
||||||
{
|
{
|
||||||
return false;
|
// 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.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(true);
|
||||||
|
sp = null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (sp == null) // We don't have an [child] agent here already
|
land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
|
||||||
{
|
|
||||||
if (requirePresenceLookup)
|
//On login test land permisions
|
||||||
|
if (vialogin)
|
||||||
{
|
{
|
||||||
try
|
if (land != null && !TestLandRestrictions(agent, land, out reason))
|
||||||
{
|
{
|
||||||
if (!VerifyUserPresence(agent, out reason))
|
|
||||||
return false;
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.ErrorFormat(
|
|
||||||
"[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
if (sp == null) // We don't have an [child] agent here already
|
||||||
{
|
{
|
||||||
if (!AuthorizeUser(agent, out reason))
|
if (requirePresenceLookup)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!VerifyUserPresence(agent, out reason))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!AuthorizeUser(agent, out reason))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception e)
|
}
|
||||||
{
|
|
||||||
m_log.ErrorFormat(
|
|
||||||
"[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_log.InfoFormat(
|
m_log.InfoFormat(
|
||||||
"[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
|
"[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
|
||||||
RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
|
RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
|
||||||
agent.AgentID, agent.circuitcode);
|
agent.AgentID, agent.circuitcode);
|
||||||
|
|
||||||
if (CapsModule != null)
|
|
||||||
{
|
|
||||||
CapsModule.SetAgentCapsSeeds(agent);
|
|
||||||
CapsModule.CreateCaps(agent.AgentID);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// Let the SP know how we got here. This has a lot of interesting
|
|
||||||
// uses down the line.
|
|
||||||
sp.TeleportFlags = (TPFlags)teleportFlags;
|
|
||||||
|
|
||||||
if (sp.IsChildAgent)
|
|
||||||
{
|
|
||||||
m_log.DebugFormat(
|
|
||||||
"[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
|
|
||||||
agent.AgentID, RegionInfo.RegionName);
|
|
||||||
|
|
||||||
sp.AdjustKnownSeeds();
|
|
||||||
|
|
||||||
if (CapsModule != null)
|
if (CapsModule != null)
|
||||||
|
{
|
||||||
CapsModule.SetAgentCapsSeeds(agent);
|
CapsModule.SetAgentCapsSeeds(agent);
|
||||||
|
CapsModule.CreateCaps(agent.AgentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Let the SP know how we got here. This has a lot of interesting
|
||||||
|
// uses down the line.
|
||||||
|
sp.TeleportFlags = (TPFlags)teleportFlags;
|
||||||
|
|
||||||
|
if (sp.IsChildAgent)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
|
||||||
|
agent.AgentID, RegionInfo.RegionName);
|
||||||
|
|
||||||
|
sp.AdjustKnownSeeds();
|
||||||
|
|
||||||
|
if (CapsModule != null)
|
||||||
|
CapsModule.SetAgentCapsSeeds(agent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4047,8 +4144,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to wait until the viewer contacts this region after receiving EAC.
|
// We have to wait until the viewer contacts this region
|
||||||
// That calls AddNewClient, which finally creates the ScenePresence
|
// after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
|
||||||
|
// a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
|
||||||
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
|
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
|
||||||
|
|
||||||
if (childAgentUpdate != null)
|
if (childAgentUpdate != null)
|
||||||
|
@ -5545,6 +5643,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void StoreExtraSetting(string name, string val)
|
public void StoreExtraSetting(string name, string val)
|
||||||
{
|
{
|
||||||
|
if (m_extraSettings == null)
|
||||||
|
return;
|
||||||
|
|
||||||
string oldVal;
|
string oldVal;
|
||||||
|
|
||||||
if (m_extraSettings.TryGetValue(name, out oldVal))
|
if (m_extraSettings.TryGetValue(name, out oldVal))
|
||||||
|
@ -5562,6 +5663,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void RemoveExtraSetting(string name)
|
public void RemoveExtraSetting(string name)
|
||||||
{
|
{
|
||||||
|
if (m_extraSettings == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!m_extraSettings.ContainsKey(name))
|
if (!m_extraSettings.ContainsKey(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -3432,6 +3432,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
|
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/*
|
||||||
public void CheckSculptAndLoad()
|
public void CheckSculptAndLoad()
|
||||||
{
|
{
|
||||||
if (IsDeleted)
|
if (IsDeleted)
|
||||||
|
@ -3447,7 +3448,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
for (int i = 0; i < parts.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
parts[i].CheckSculptAndLoad();
|
parts[i].CheckSculptAndLoad();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the user group to which this scene object belongs.
|
/// Set the user group to which this scene object belongs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1014,9 +1014,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
actor.Size = m_shape.Scale;
|
actor.Size = m_shape.Scale;
|
||||||
|
|
||||||
if (Shape.SculptEntry)
|
// if (Shape.SculptEntry)
|
||||||
CheckSculptAndLoad();
|
// CheckSculptAndLoad();
|
||||||
else
|
// else
|
||||||
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1620,12 +1620,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (userExposed)
|
if (userExposed)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
|
if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
|
||||||
{
|
{
|
||||||
ParentGroup.Scene.AssetService.Get(
|
ParentGroup.Scene.AssetService.Get(
|
||||||
dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
|
dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
|
bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
|
||||||
dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
|
dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
|
||||||
}
|
}
|
||||||
|
@ -1643,6 +1644,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="id">ID of asset received</param>
|
/// <param name="id">ID of asset received</param>
|
||||||
/// <param name="sender">Register</param>
|
/// <param name="sender">Register</param>
|
||||||
/// <param name="asset"></param>
|
/// <param name="asset"></param>
|
||||||
|
/*
|
||||||
protected void AssetReceived(string id, Object sender, AssetBase asset)
|
protected void AssetReceived(string id, Object sender, AssetBase asset)
|
||||||
{
|
{
|
||||||
if (asset != null)
|
if (asset != null)
|
||||||
|
@ -1652,7 +1654,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
"[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
|
"[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
|
||||||
Name, UUID, id);
|
Name, UUID, id);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Do a physics property update for a NINJA joint.
|
/// Do a physics property update for a NINJA joint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1833,9 +1835,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// If this part is a sculpt then delay the physics update until we've asynchronously loaded the
|
// If this part is a sculpt then delay the physics update until we've asynchronously loaded the
|
||||||
// mesh data.
|
// mesh data.
|
||||||
if (Shape.SculptEntry)
|
// if (Shape.SculptEntry)
|
||||||
CheckSculptAndLoad();
|
// CheckSculptAndLoad();
|
||||||
else
|
// else
|
||||||
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
|
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2465,7 +2467,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// UUID, Name, TimeStampFull);
|
// UUID, Name, TimeStampFull);
|
||||||
|
|
||||||
if (ParentGroup.Scene != null)
|
if (ParentGroup.Scene != null)
|
||||||
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this);
|
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2499,7 +2501,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParentGroup.Scene != null)
|
if (ParentGroup.Scene != null)
|
||||||
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this);
|
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScriptSetPhysicsStatus(bool UsePhysics)
|
public void ScriptSetPhysicsStatus(bool UsePhysics)
|
||||||
|
@ -2511,6 +2513,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// Set sculpt and mesh data, and tell the physics engine to process the change.
|
/// Set sculpt and mesh data, and tell the physics engine to process the change.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="texture">The mesh itself.</param>
|
/// <param name="texture">The mesh itself.</param>
|
||||||
|
/*
|
||||||
public void SculptTextureCallback(AssetBase texture)
|
public void SculptTextureCallback(AssetBase texture)
|
||||||
{
|
{
|
||||||
if (m_shape.SculptEntry)
|
if (m_shape.SculptEntry)
|
||||||
|
@ -2538,7 +2541,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a full update to the client for the given part
|
/// Send a full update to the client for the given part
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -3783,7 +3786,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
|
public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
|
||||||
{
|
{
|
||||||
m_shape.ReadInUpdateExtraParam(type, inUse, data);
|
m_shape.ReadInUpdateExtraParam(type, inUse, data);
|
||||||
|
/*
|
||||||
if (type == 0x30)
|
if (type == 0x30)
|
||||||
{
|
{
|
||||||
if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
|
if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
|
||||||
|
@ -3791,7 +3794,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived);
|
ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (ParentGroup != null)
|
if (ParentGroup != null)
|
||||||
{
|
{
|
||||||
ParentGroup.HasGroupChanged = true;
|
ParentGroup.HasGroupChanged = true;
|
||||||
|
@ -4025,14 +4028,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (!wasUsingPhysics)
|
if (!wasUsingPhysics)
|
||||||
{
|
{
|
||||||
DoPhysicsPropertyUpdate(UsePhysics, false);
|
DoPhysicsPropertyUpdate(UsePhysics, false);
|
||||||
|
|
||||||
if (!ParentGroup.IsDeleted)
|
|
||||||
{
|
|
||||||
if (LocalId == ParentGroup.RootPart.LocalId)
|
|
||||||
{
|
|
||||||
ParentGroup.CheckSculptAndLoad();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4072,14 +4067,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
pa.SetMaterial(Material);
|
pa.SetMaterial(Material);
|
||||||
DoPhysicsPropertyUpdate(UsePhysics, true);
|
DoPhysicsPropertyUpdate(UsePhysics, true);
|
||||||
|
|
||||||
if (!ParentGroup.IsDeleted)
|
|
||||||
{
|
|
||||||
if (LocalId == ParentGroup.RootPart.LocalId)
|
|
||||||
{
|
|
||||||
ParentGroup.CheckSculptAndLoad();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
((AggregateScriptEvents & scriptEvents.collision) != 0) ||
|
((AggregateScriptEvents & scriptEvents.collision) != 0) ||
|
||||||
((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
|
((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
|
||||||
|
@ -4104,14 +4091,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
else // it already has a physical representation
|
else // it already has a physical representation
|
||||||
{
|
{
|
||||||
DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
|
DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
|
||||||
|
|
||||||
if (!ParentGroup.IsDeleted)
|
|
||||||
{
|
|
||||||
if (LocalId == ParentGroup.RootPart.LocalId)
|
|
||||||
{
|
|
||||||
ParentGroup.CheckSculptAndLoad();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4341,6 +4320,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
|
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/*
|
||||||
public void CheckSculptAndLoad()
|
public void CheckSculptAndLoad()
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
|
// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
|
||||||
|
@ -4366,7 +4346,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update the texture entry for this part.
|
/// Update the texture entry for this part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -4604,6 +4584,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations);
|
Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations);
|
||||||
|
rot.Normalize();
|
||||||
UpdateRotation(rot);
|
UpdateRotation(rot);
|
||||||
|
|
||||||
m_APIDIterations--;
|
m_APIDIterations--;
|
||||||
|
|
|
@ -93,6 +93,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (m_items)
|
||||||
|
return m_items.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -47,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates";
|
public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates";
|
||||||
|
public const string SlowFramesStatName = "SlowFrames";
|
||||||
|
|
||||||
public delegate void SendStatResult(SimStats stats);
|
public delegate void SendStatResult(SimStats stats);
|
||||||
|
|
||||||
|
@ -128,6 +129,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
get { return lastReportedSimStats; }
|
get { return lastReportedSimStats; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME
|
||||||
|
/// </summary>
|
||||||
|
public Stat SlowFramesStat { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The threshold at which we log a slow frame.
|
||||||
|
/// </summary>
|
||||||
|
public int SlowFramesStatReportThreshold { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extra sim statistics that are used by monitors but not sent to the client.
|
/// Extra sim statistics that are used by monitors but not sent to the client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -225,6 +236,22 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (StatsManager.SimExtraStats != null)
|
if (StatsManager.SimExtraStats != null)
|
||||||
OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
|
OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
|
||||||
|
|
||||||
|
/// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
|
||||||
|
/// longer than ideal (which in itself is a concern).
|
||||||
|
SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2);
|
||||||
|
|
||||||
|
SlowFramesStat
|
||||||
|
= new Stat(
|
||||||
|
"SlowFrames",
|
||||||
|
"Slow Frames",
|
||||||
|
" frames",
|
||||||
|
"scene",
|
||||||
|
m_scene.Name,
|
||||||
|
StatVerbosity.Info,
|
||||||
|
"Number of frames where frame time has been significantly longer than the desired frame time.");
|
||||||
|
|
||||||
|
StatsManager.RegisterStat(SlowFramesStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
|
@ -418,6 +445,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
lock (m_lastReportedExtraSimStats)
|
lock (m_lastReportedExtraSimStats)
|
||||||
{
|
{
|
||||||
m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor;
|
m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor;
|
||||||
|
m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
|
||||||
|
|
||||||
Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
|
Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
|
||||||
|
|
||||||
|
@ -535,6 +563,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public void addFrameMS(int ms)
|
public void addFrameMS(int ms)
|
||||||
{
|
{
|
||||||
m_frameMS += ms;
|
m_frameMS += ms;
|
||||||
|
|
||||||
|
// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
|
||||||
|
// longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern).
|
||||||
|
if (ms > SlowFramesStatReportThreshold)
|
||||||
|
SlowFramesStat.Value++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSpareMS(int ms)
|
public void AddSpareMS(int ms)
|
||||||
|
|
|
@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
||||||
sb.AppendFormat("Attachments for {0}\n", sp.Name);
|
sb.AppendFormat("Attachments for {0}\n", sp.Name);
|
||||||
|
|
||||||
ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 };
|
ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 };
|
||||||
ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36));
|
ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50));
|
||||||
ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10));
|
ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10));
|
||||||
ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36));
|
ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36));
|
||||||
ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14));
|
ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14));
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
OnInstantMessage(this, new GridInstantMessage(m_scene,
|
OnInstantMessage(this, new GridInstantMessage(m_scene,
|
||||||
m_uuid, m_firstname + " " + m_lastname,
|
m_uuid, m_firstname + " " + m_lastname,
|
||||||
target, 0, false, message,
|
target, 0, false, message,
|
||||||
UUID.Zero, false, Position, new byte[0]));
|
UUID.Zero, false, Position, new byte[0], true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAgentOffline(UUID[] agentIDs)
|
public void SendAgentOffline(UUID[] agentIDs)
|
||||||
|
|
|
@ -218,6 +218,18 @@ public class BSCharacter : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override OMV.Vector3 ForcePosition {
|
||||||
|
get {
|
||||||
|
_position = BulletSimAPI.GetPosition2(BSBody.ptr);
|
||||||
|
return _position;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_position = value;
|
||||||
|
PositionSanityCheck();
|
||||||
|
BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check that the current position is sane and, if not, modify the position to make it so.
|
// Check that the current position is sane and, if not, modify the position to make it so.
|
||||||
// Check for being below terrain and being out of bounds.
|
// Check for being below terrain and being out of bounds.
|
||||||
|
@ -234,6 +246,15 @@ public class BSCharacter : BSPhysObject
|
||||||
_position.Z = terrainHeight + 2.0f;
|
_position.Z = terrainHeight + 2.0f;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
|
||||||
|
{
|
||||||
|
float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
|
||||||
|
if (Position.Z < waterHeight)
|
||||||
|
{
|
||||||
|
_position.Z = waterHeight;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check for out of bounds
|
// TODO: check for out of bounds
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -242,18 +263,22 @@ public class BSCharacter : BSPhysObject
|
||||||
// A version of the sanity check that also makes sure a new position value is
|
// A version of the sanity check that also makes sure a new position value is
|
||||||
// pushed back to the physics engine. This routine would be used by anyone
|
// pushed back to the physics engine. This routine would be used by anyone
|
||||||
// who is not already pushing the value.
|
// who is not already pushing the value.
|
||||||
private bool PositionSanityCheck2()
|
private bool PositionSanityCheck2(bool inTaintTime)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (PositionSanityCheck())
|
if (PositionSanityCheck())
|
||||||
{
|
{
|
||||||
// The new position value must be pushed into the physics engine but we can't
|
// The new position value must be pushed into the physics engine but we can't
|
||||||
// just assign to "Position" because of potential call loops.
|
// just assign to "Position" because of potential call loops.
|
||||||
PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
|
BSScene.TaintCallback sanityOperation = delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
|
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
|
||||||
});
|
};
|
||||||
|
if (inTaintTime)
|
||||||
|
sanityOperation();
|
||||||
|
else
|
||||||
|
PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -307,6 +332,13 @@ public class BSCharacter : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override OMV.Vector3 ForceVelocity {
|
||||||
|
get { return _velocity; }
|
||||||
|
set {
|
||||||
|
_velocity = value;
|
||||||
|
BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
public override OMV.Vector3 Torque {
|
public override OMV.Vector3 Torque {
|
||||||
get { return _torque; }
|
get { return _torque; }
|
||||||
set { _torque = value;
|
set { _torque = value;
|
||||||
|
@ -333,6 +365,20 @@ public class BSCharacter : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Go directly to Bullet to get/set the value.
|
||||||
|
public override OMV.Quaternion ForceOrientation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
_orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
|
||||||
|
return _orientation;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_orientation = value;
|
||||||
|
BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
public override int PhysicsActorType {
|
public override int PhysicsActorType {
|
||||||
get { return _physicsActorType; }
|
get { return _physicsActorType; }
|
||||||
set { _physicsActorType = value;
|
set { _physicsActorType = value;
|
||||||
|
@ -378,12 +424,25 @@ public class BSCharacter : BSPhysObject
|
||||||
set { _collidingObj = value; }
|
set { _collidingObj = value; }
|
||||||
}
|
}
|
||||||
public override bool FloatOnWater {
|
public override bool FloatOnWater {
|
||||||
set { _floatOnWater = value; }
|
set {
|
||||||
|
_floatOnWater = value;
|
||||||
|
PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
|
||||||
|
{
|
||||||
|
if (_floatOnWater)
|
||||||
|
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
||||||
|
else
|
||||||
|
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 RotationalVelocity {
|
public override OMV.Vector3 RotationalVelocity {
|
||||||
get { return _rotationalVelocity; }
|
get { return _rotationalVelocity; }
|
||||||
set { _rotationalVelocity = value; }
|
set { _rotationalVelocity = value; }
|
||||||
}
|
}
|
||||||
|
public override OMV.Vector3 ForceRotationalVelocity {
|
||||||
|
get { return _rotationalVelocity; }
|
||||||
|
set { _rotationalVelocity = value; }
|
||||||
|
}
|
||||||
public override bool Kinematic {
|
public override bool Kinematic {
|
||||||
get { return _kinematic; }
|
get { return _kinematic; }
|
||||||
set { _kinematic = value; }
|
set { _kinematic = value; }
|
||||||
|
@ -493,15 +552,14 @@ public class BSCharacter : BSPhysObject
|
||||||
_velocity = entprop.Velocity;
|
_velocity = entprop.Velocity;
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
_rotationalVelocity = entprop.RotationalVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
// Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
|
||||||
|
PositionSanityCheck2(true);
|
||||||
|
|
||||||
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
|
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
|
||||||
// base.RequestPhysicsterseUpdate();
|
// base.RequestPhysicsterseUpdate();
|
||||||
|
|
||||||
// Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
|
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||||
PositionSanityCheck2();
|
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
|
||||||
|
|
||||||
float heightHere = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
|
|
||||||
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
|
|
||||||
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,16 @@ public abstract class BSConstraint : IDisposable
|
||||||
if (m_enabled)
|
if (m_enabled)
|
||||||
{
|
{
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
|
if (m_constraint.ptr != IntPtr.Zero)
|
||||||
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
|
{
|
||||||
m_constraint.ptr = System.IntPtr.Zero;
|
bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
|
||||||
|
m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
|
||||||
|
BSScene.DetailLogZero,
|
||||||
|
m_body1.ID, m_body1.ptr.ToString("X"),
|
||||||
|
m_body2.ID, m_body2.ptr.ToString("X"),
|
||||||
|
success);
|
||||||
|
m_constraint.ptr = System.IntPtr.Zero;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay 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_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
|
||||||
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
|
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
|
||||||
// private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
|
private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
|
||||||
|
|
||||||
//Deflection properties
|
//Deflection properties
|
||||||
// private float m_angularDeflectionEfficiency = 0;
|
// private float m_angularDeflectionEfficiency = 0;
|
||||||
|
@ -138,74 +138,55 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
switch (pParam)
|
switch (pParam)
|
||||||
{
|
{
|
||||||
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
|
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
// m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f);
|
||||||
// m_angularDeflectionEfficiency = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
|
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
// m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
|
||||||
// m_angularDeflectionTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
|
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f);
|
||||||
m_angularMotorDecayTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
|
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
m_angularMotorTimescale = Math.Max(pValue, 0.01f);
|
||||||
m_angularMotorTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.BANKING_EFFICIENCY:
|
case Vehicle.BANKING_EFFICIENCY:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
// m_bankingEfficiency = Math.Max(pValue, 0.01f);
|
||||||
// m_bankingEfficiency = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.BANKING_MIX:
|
case Vehicle.BANKING_MIX:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
// m_bankingMix = Math.Max(pValue, 0.01f);
|
||||||
// m_bankingMix = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.BANKING_TIMESCALE:
|
case Vehicle.BANKING_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
// m_bankingTimescale = Math.Max(pValue, 0.01f);
|
||||||
// m_bankingTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.BUOYANCY:
|
case Vehicle.BUOYANCY:
|
||||||
if (pValue < -1f) pValue = -1f;
|
m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f));
|
||||||
if (pValue > 1f) pValue = 1f;
|
|
||||||
m_VehicleBuoyancy = pValue;
|
|
||||||
break;
|
break;
|
||||||
// case Vehicle.HOVER_EFFICIENCY:
|
// case Vehicle.HOVER_EFFICIENCY:
|
||||||
// if (pValue < 0f) pValue = 0f;
|
// m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f));
|
||||||
// if (pValue > 1f) pValue = 1f;
|
|
||||||
// m_VhoverEfficiency = pValue;
|
|
||||||
// break;
|
// break;
|
||||||
case Vehicle.HOVER_HEIGHT:
|
case Vehicle.HOVER_HEIGHT:
|
||||||
m_VhoverHeight = pValue;
|
m_VhoverHeight = pValue;
|
||||||
break;
|
break;
|
||||||
case Vehicle.HOVER_TIMESCALE:
|
case Vehicle.HOVER_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
m_VhoverTimescale = Math.Max(pValue, 0.01f);
|
||||||
m_VhoverTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
|
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
// m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
|
||||||
// m_linearDeflectionEfficiency = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
|
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
// m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
|
||||||
// m_linearDeflectionTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
|
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f);
|
||||||
m_linearMotorDecayTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_MOTOR_TIMESCALE:
|
case Vehicle.LINEAR_MOTOR_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
m_linearMotorTimescale = Math.Max(pValue, 0.01f);
|
||||||
m_linearMotorTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
|
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
|
||||||
if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
|
m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
|
||||||
if (pValue > 1.0f) pValue = 1.0f;
|
|
||||||
m_verticalAttractionEfficiency = pValue;
|
|
||||||
break;
|
break;
|
||||||
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
|
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
|
||||||
if (pValue < 0.01f) pValue = 0.01f;
|
m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
|
||||||
m_verticalAttractionTimescale = pValue;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// These are vector properties but the engine lets you use a single float value to
|
// These are vector properties but the engine lets you use a single float value to
|
||||||
|
@ -371,8 +352,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// m_bankingMix = 1;
|
// m_bankingMix = 1;
|
||||||
// m_bankingTimescale = 1;
|
// m_bankingTimescale = 1;
|
||||||
// m_referenceFrame = Quaternion.Identity;
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
|
m_flags |= (VehicleFlag.NO_DEFLECTION_UP
|
||||||
VehicleFlag.LIMIT_MOTOR_UP);
|
| VehicleFlag.LIMIT_ROLL_ONLY
|
||||||
|
| VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||||
m_flags |= (VehicleFlag.HOVER_UP_ONLY);
|
m_flags |= (VehicleFlag.HOVER_UP_ONLY);
|
||||||
break;
|
break;
|
||||||
|
@ -399,12 +381,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// m_bankingMix = 0.8f;
|
// m_bankingMix = 0.8f;
|
||||||
// m_bankingTimescale = 1;
|
// m_bankingTimescale = 1;
|
||||||
// m_referenceFrame = Quaternion.Identity;
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
|
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
|
||||||
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
|
| VehicleFlag.HOVER_GLOBAL_HEIGHT
|
||||||
m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
|
| VehicleFlag.LIMIT_ROLL_ONLY
|
||||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
|
| VehicleFlag.HOVER_UP_ONLY);
|
||||||
VehicleFlag.LIMIT_MOTOR_UP);
|
m_flags |= (VehicleFlag.NO_DEFLECTION_UP
|
||||||
m_flags |= (VehicleFlag.HOVER_WATER_ONLY);
|
| VehicleFlag.LIMIT_MOTOR_UP
|
||||||
|
| VehicleFlag.HOVER_WATER_ONLY);
|
||||||
break;
|
break;
|
||||||
case Vehicle.TYPE_AIRPLANE:
|
case Vehicle.TYPE_AIRPLANE:
|
||||||
m_linearFrictionTimescale = new Vector3(200, 10, 5);
|
m_linearFrictionTimescale = new Vector3(200, 10, 5);
|
||||||
|
@ -429,9 +412,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// m_bankingMix = 0.7f;
|
// m_bankingMix = 0.7f;
|
||||||
// m_bankingTimescale = 2;
|
// m_bankingTimescale = 2;
|
||||||
// m_referenceFrame = Quaternion.Identity;
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
|
||||||
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
|
| VehicleFlag.HOVER_TERRAIN_ONLY
|
||||||
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
|
| VehicleFlag.HOVER_GLOBAL_HEIGHT
|
||||||
|
| VehicleFlag.HOVER_UP_ONLY
|
||||||
|
| VehicleFlag.NO_DEFLECTION_UP
|
||||||
|
| VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
|
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
|
||||||
break;
|
break;
|
||||||
case Vehicle.TYPE_BALLOON:
|
case Vehicle.TYPE_BALLOON:
|
||||||
|
@ -457,11 +443,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// m_bankingMix = 0.7f;
|
// m_bankingMix = 0.7f;
|
||||||
// m_bankingTimescale = 5;
|
// m_bankingTimescale = 5;
|
||||||
// m_referenceFrame = Quaternion.Identity;
|
// m_referenceFrame = Quaternion.Identity;
|
||||||
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
|
||||||
VehicleFlag.HOVER_UP_ONLY);
|
| VehicleFlag.HOVER_TERRAIN_ONLY
|
||||||
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
|
| VehicleFlag.HOVER_UP_ONLY
|
||||||
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
|
| VehicleFlag.NO_DEFLECTION_UP
|
||||||
m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
| VehicleFlag.LIMIT_MOTOR_UP);
|
||||||
|
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY
|
||||||
|
| VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}//end SetDefaultsForType
|
}//end SetDefaultsForType
|
||||||
|
@ -470,10 +458,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// Do any updating needed for a vehicle
|
// Do any updating needed for a vehicle
|
||||||
public void Refresh()
|
public void Refresh()
|
||||||
{
|
{
|
||||||
if (Type == Vehicle.TYPE_NONE) return;
|
if (!IsActive)
|
||||||
|
return;
|
||||||
|
|
||||||
// Set the prim's inertia to zero. The vehicle code handles that and this
|
// Set the prim's inertia to zero. The vehicle code handles that and this
|
||||||
// removes the torque action introduced by Bullet.
|
// removes the motion and torque actions introduced by Bullet.
|
||||||
Vector3 inertia = Vector3.Zero;
|
Vector3 inertia = Vector3.Zero;
|
||||||
BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia);
|
BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia);
|
||||||
BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr);
|
BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr);
|
||||||
|
@ -489,10 +478,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
LimitRotation(pTimestep);
|
LimitRotation(pTimestep);
|
||||||
|
|
||||||
// remember the position so next step we can limit absolute movement effects
|
// remember the position so next step we can limit absolute movement effects
|
||||||
m_lastPositionVector = Prim.Position;
|
m_lastPositionVector = Prim.ForcePosition;
|
||||||
|
|
||||||
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
|
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
|
||||||
Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity);
|
Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
|
||||||
}// end Step
|
}// end Step
|
||||||
|
|
||||||
// Apply the effect of the linear motor.
|
// Apply the effect of the linear motor.
|
||||||
|
@ -543,7 +532,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert requested object velocity to object relative vector
|
// convert requested object velocity to object relative vector
|
||||||
Quaternion rotq = Prim.Orientation;
|
Quaternion rotq = Prim.ForceOrientation;
|
||||||
m_newVelocity = m_lastLinearVelocityVector * rotq;
|
m_newVelocity = m_lastLinearVelocityVector * rotq;
|
||||||
|
|
||||||
// Add the various forces into m_dir which will be our new direction vector (velocity)
|
// Add the various forces into m_dir which will be our new direction vector (velocity)
|
||||||
|
@ -551,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// add Gravity and Buoyancy
|
// add Gravity and Buoyancy
|
||||||
// There is some gravity, make a gravity force vector that is applied after object velocity.
|
// There is some gravity, make a gravity force vector that is applied after object velocity.
|
||||||
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
|
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
|
||||||
Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Mass * (1f - m_VehicleBuoyancy));
|
Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RA: Not sure why one would do this
|
* RA: Not sure why one would do this
|
||||||
|
@ -560,19 +549,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
|
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Vector3 pos = Prim.Position;
|
Vector3 pos = Prim.ForcePosition;
|
||||||
// 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 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);
|
||||||
|
|
||||||
// If below the terrain, move us above the ground a little.
|
// If below the terrain, move us above the ground a little.
|
||||||
float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
||||||
// Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
|
// Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
|
||||||
// Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
|
// Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
|
||||||
// Vector3 rotatedSize = m_prim.Size * m_prim.Orientation;
|
// Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
|
||||||
// if (rotatedSize.Z < terrainHeight)
|
// if (rotatedSize.Z < terrainHeight)
|
||||||
if (pos.Z < terrainHeight)
|
if (pos.Z < terrainHeight)
|
||||||
{
|
{
|
||||||
pos.Z = terrainHeight + 2;
|
pos.Z = terrainHeight + 2;
|
||||||
Prim.Position = pos;
|
Prim.ForcePosition = pos;
|
||||||
VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
|
VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +591,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
|
if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
|
||||||
{
|
{
|
||||||
Prim.Position = pos;
|
Prim.ForcePosition = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -654,12 +643,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
Prim.Position = pos;
|
Prim.ForcePosition = pos;
|
||||||
VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
|
VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
|
||||||
Prim.LocalID, m_BlockingEndPoint, posChange, pos);
|
Prim.LocalID, m_BlockingEndPoint, posChange, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit absolute vertical change
|
||||||
float Zchange = Math.Abs(posChange.Z);
|
float Zchange = Math.Abs(posChange.Z);
|
||||||
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
|
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
|
||||||
{
|
{
|
||||||
|
@ -678,6 +668,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
grav.Z = (float)(grav.Z * 1.037125);
|
grav.Z = (float)(grav.Z * 1.037125);
|
||||||
VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav);
|
VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If not changing some axis, reduce out velocity
|
||||||
if ((m_flags & (VehicleFlag.NO_X)) != 0)
|
if ((m_flags & (VehicleFlag.NO_X)) != 0)
|
||||||
m_newVelocity.X = 0;
|
m_newVelocity.X = 0;
|
||||||
if ((m_flags & (VehicleFlag.NO_Y)) != 0)
|
if ((m_flags & (VehicleFlag.NO_Y)) != 0)
|
||||||
|
@ -686,10 +678,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_newVelocity.Z = 0;
|
m_newVelocity.Z = 0;
|
||||||
|
|
||||||
// Apply velocity
|
// Apply velocity
|
||||||
Prim.Velocity = m_newVelocity;
|
Prim.ForceVelocity = m_newVelocity;
|
||||||
// apply gravity force
|
// apply gravity force
|
||||||
// Why is this set here? The physics engine already does gravity.
|
// Why is this set here? The physics engine already does gravity.
|
||||||
// m_prim.AddForce(grav, false);
|
Prim.AddForce(grav, false, true);
|
||||||
|
|
||||||
// Apply friction
|
// Apply friction
|
||||||
Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
|
Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
|
||||||
|
@ -712,7 +704,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// m_lastAngularVelocity // what was last applied to body
|
// m_lastAngularVelocity // what was last applied to body
|
||||||
|
|
||||||
// Get what the body is doing, this includes 'external' influences
|
// Get what the body is doing, this includes 'external' influences
|
||||||
Vector3 angularVelocity = Prim.RotationalVelocity;
|
Vector3 angularVelocity = Prim.ForceRotationalVelocity;
|
||||||
|
|
||||||
if (m_angularMotorApply > 0)
|
if (m_angularMotorApply > 0)
|
||||||
{
|
{
|
||||||
|
@ -720,19 +712,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// a newly set velocity, this routine steps the value from the previous
|
// a newly set velocity, this routine steps the value from the previous
|
||||||
// value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
|
// value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
|
||||||
// There are m_angularMotorApply steps.
|
// There are m_angularMotorApply steps.
|
||||||
Vector3 origAngularVelocity = m_angularMotorVelocity;
|
Vector3 origVel = m_angularMotorVelocity;
|
||||||
|
Vector3 origDir = m_angularMotorDirection;
|
||||||
|
|
||||||
// ramp up to new value
|
// ramp up to new value
|
||||||
// current velocity += error / ( time to get there / step interval)
|
// new velocity += error / ( time to get there / step interval)
|
||||||
// requested speed - last motor speed
|
// requested speed - last motor speed
|
||||||
m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
|
m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
|
||||||
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
|
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
|
||||||
m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
|
m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
|
||||||
|
|
||||||
VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}",
|
VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}",
|
||||||
Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
|
Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
|
||||||
|
|
||||||
// This is done so that if script request rate is less than phys frame rate the expected
|
|
||||||
// velocity may still be acheived.
|
|
||||||
m_angularMotorApply--;
|
m_angularMotorApply--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -746,25 +738,32 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
|
||||||
// Vertical attractor section
|
// Vertical attractor section
|
||||||
Vector3 vertattr = Vector3.Zero;
|
Vector3 vertattr = Vector3.Zero;
|
||||||
if (m_verticalAttractionTimescale < 300)
|
Vector3 deflection = Vector3.Zero;
|
||||||
|
Vector3 banking = Vector3.Zero;
|
||||||
|
|
||||||
|
if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero)
|
||||||
{
|
{
|
||||||
float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
|
float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
|
||||||
|
VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
|
||||||
|
|
||||||
// get present body rotation
|
// get present body rotation
|
||||||
Quaternion rotq = Prim.Orientation;
|
Quaternion rotq = Prim.ForceOrientation;
|
||||||
// make a vector pointing up
|
// vector pointing up
|
||||||
Vector3 verterr = Vector3.Zero;
|
Vector3 verterr = Vector3.Zero;
|
||||||
verterr.Z = 1.0f;
|
verterr.Z = 1.0f;
|
||||||
|
|
||||||
// rotate it to Body Angle
|
// rotate it to Body Angle
|
||||||
verterr = verterr * rotq;
|
verterr = verterr * rotq;
|
||||||
// verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
|
// verterr.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
|
||||||
// As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
|
// As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
|
||||||
// negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
|
// negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
|
||||||
|
|
||||||
|
// Error is 0 (no error) to +/- 2 (max error)
|
||||||
if (verterr.Z < 0.0f)
|
if (verterr.Z < 0.0f)
|
||||||
{
|
{
|
||||||
verterr.X = 2.0f - verterr.X;
|
verterr.X = 2.0f - verterr.X;
|
||||||
verterr.Y = 2.0f - verterr.Y;
|
verterr.Y = 2.0f - verterr.Y;
|
||||||
}
|
}
|
||||||
// Error is 0 (no error) to +/- 2 (max error)
|
|
||||||
// scale it by VAservo
|
// scale it by VAservo
|
||||||
verterr = verterr * VAservo;
|
verterr = verterr * VAservo;
|
||||||
|
|
||||||
|
@ -784,7 +783,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
|
||||||
} // else vertical attractor is off
|
} // else vertical attractor is off
|
||||||
|
|
||||||
// m_lastVertAttractor = vertattr;
|
m_lastVertAttractor = vertattr;
|
||||||
|
|
||||||
// Bank section tba
|
// Bank section tba
|
||||||
|
|
||||||
|
@ -811,14 +810,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
|
m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
|
||||||
|
|
||||||
// Apply to the body
|
// Apply to the body
|
||||||
Prim.RotationalVelocity = m_lastAngularVelocity;
|
Prim.ForceRotationalVelocity = m_lastAngularVelocity;
|
||||||
|
|
||||||
VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity);
|
VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity);
|
||||||
} //end MoveAngular
|
} //end MoveAngular
|
||||||
|
|
||||||
internal void LimitRotation(float timestep)
|
internal void LimitRotation(float timestep)
|
||||||
{
|
{
|
||||||
Quaternion rotq = Prim.Orientation;
|
Quaternion rotq = Prim.ForceOrientation;
|
||||||
Quaternion m_rot = rotq;
|
Quaternion m_rot = rotq;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
if (m_RollreferenceFrame != Quaternion.Identity)
|
if (m_RollreferenceFrame != Quaternion.Identity)
|
||||||
|
@ -853,7 +852,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
Prim.Orientation = m_rot;
|
Prim.ForceOrientation = m_rot;
|
||||||
VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
|
VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,7 +862,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
private void VDetailLog(string msg, params Object[] args)
|
private void VDetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
if (Prim.PhysicsScene.VehicleLoggingEnabled)
|
if (Prim.PhysicsScene.VehicleLoggingEnabled)
|
||||||
Prim.PhysicsScene.PhysicsLogging.Write(msg, args);
|
Prim.PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
public class BSLinkset
|
public class BSLinkset
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM LINKSET]";
|
// private static string LogHeader = "[BULLETSIM LINKSET]";
|
||||||
|
|
||||||
public BSPhysObject LinksetRoot { get; protected set; }
|
public BSPhysObject LinksetRoot { get; protected set; }
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ public class BSLinkset
|
||||||
// the physical 'taint' children separately.
|
// the physical 'taint' children separately.
|
||||||
// After taint processing and before the simulation step, these
|
// After taint processing and before the simulation step, these
|
||||||
// two lists must be the same.
|
// two lists must be the same.
|
||||||
private List<BSPhysObject> m_children;
|
private HashSet<BSPhysObject> m_children;
|
||||||
private List<BSPhysObject> m_taintChildren;
|
private HashSet<BSPhysObject> m_taintChildren;
|
||||||
|
|
||||||
// We lock the diddling of linkset classes to prevent any badness.
|
// We lock the diddling of linkset classes to prevent any badness.
|
||||||
// This locks the modification of the instances of this class. Changes
|
// This locks the modification of the instances of this class. Changes
|
||||||
|
@ -90,8 +90,8 @@ public class BSLinkset
|
||||||
m_nextLinksetID = 1;
|
m_nextLinksetID = 1;
|
||||||
PhysicsScene = scene;
|
PhysicsScene = scene;
|
||||||
LinksetRoot = parent;
|
LinksetRoot = parent;
|
||||||
m_children = new List<BSPhysObject>();
|
m_children = new HashSet<BSPhysObject>();
|
||||||
m_taintChildren = new List<BSPhysObject>();
|
m_taintChildren = new HashSet<BSPhysObject>();
|
||||||
m_mass = parent.MassRaw;
|
m_mass = parent.MassRaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,6 +160,28 @@ public class BSLinkset
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
|
// its internal properties.
|
||||||
|
// May be called at runtime or taint-time (just pass the appropriate flag).
|
||||||
|
public void Refresh(BSPhysObject requestor, bool inTaintTime)
|
||||||
|
{
|
||||||
|
// If there are no children, not physical or not root, I am not the one that recomputes the constraints
|
||||||
|
// (For the moment, static linksets do create constraints so remove the test for physical.)
|
||||||
|
if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BSScene.TaintCallback refreshOperation = delegate()
|
||||||
|
{
|
||||||
|
RecomputeLinksetConstraintVariables();
|
||||||
|
DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}",
|
||||||
|
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
|
||||||
|
};
|
||||||
|
if (inTaintTime)
|
||||||
|
refreshOperation();
|
||||||
|
else
|
||||||
|
PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation);
|
||||||
|
}
|
||||||
|
|
||||||
// The object is going dynamic (physical). Do any setup necessary
|
// The object is going dynamic (physical). Do any setup necessary
|
||||||
// for a dynamic linkset.
|
// for a dynamic linkset.
|
||||||
// Only the state of the passed object can be modified. The rest of the linkset
|
// Only the state of the passed object can be modified. The rest of the linkset
|
||||||
|
@ -182,22 +204,19 @@ public class BSLinkset
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// If the software is handling the movement of all the objects in a linkset
|
||||||
// its internal properties.
|
// (like if one doesn't use constraints for static linksets), this is called
|
||||||
// Called at runtime.
|
// when an update for the root of the linkset is received.
|
||||||
public void Refresh(BSPhysObject requestor)
|
// Called at taint-time!!
|
||||||
|
public void UpdateProperties(BSPhysObject physObject)
|
||||||
{
|
{
|
||||||
// If there are no children, there can't be any constraints to recompute
|
// The root local properties have been updated. Apply to the children if appropriate.
|
||||||
if (!HasAnyChildren)
|
if (IsRoot(physObject) && HasAnyChildren)
|
||||||
return;
|
|
||||||
|
|
||||||
// Only the root does the recomputation
|
|
||||||
if (IsRoot(requestor))
|
|
||||||
{
|
{
|
||||||
PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
|
if (!physObject.IsPhysical)
|
||||||
{
|
{
|
||||||
RecomputeLinksetConstraintVariables();
|
// TODO: implement software linkset update for static object linksets
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,13 +234,10 @@ public class BSLinkset
|
||||||
if (IsRoot(child))
|
if (IsRoot(child))
|
||||||
{
|
{
|
||||||
// If the one with the dependency is root, must undo all children
|
// If the one with the dependency is root, must undo all children
|
||||||
DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}",
|
DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
|
||||||
child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
|
child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
|
||||||
foreach (BSPhysObject bpo in m_taintChildren)
|
|
||||||
{
|
ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
|
||||||
PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -229,20 +245,16 @@ public class BSLinkset
|
||||||
child.LocalID,
|
child.LocalID,
|
||||||
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
||||||
child.LocalID, child.BSBody.ptr.ToString("X"));
|
child.LocalID, child.BSBody.ptr.ToString("X"));
|
||||||
// Remove the dependency on the body of this one
|
// ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child);
|
||||||
if (m_taintChildren.Contains(child))
|
// Despite the function name, this removes any link to the specified object.
|
||||||
{
|
ret = PhysicallyUnlinkAllChildrenFromRoot(child);
|
||||||
PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine used when rebuilding the body of the root of the linkset
|
// Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
|
||||||
// This is called after RemoveAllLinksToRoot() to restore all the constraints.
|
// this routine will restore the removed constraints.
|
||||||
// This is called when the root body has been changed.
|
|
||||||
// Called at taint-time!!
|
// Called at taint-time!!
|
||||||
public void RestoreBodyDependencies(BSPrim child)
|
public void RestoreBodyDependencies(BSPrim child)
|
||||||
{
|
{
|
||||||
|
@ -254,7 +266,7 @@ public class BSLinkset
|
||||||
child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
|
child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
|
||||||
foreach (BSPhysObject bpo in m_taintChildren)
|
foreach (BSPhysObject bpo in m_taintChildren)
|
||||||
{
|
{
|
||||||
PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody);
|
PhysicallyLinkAChildToRoot(LinksetRoot, bpo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -263,7 +275,7 @@ public class BSLinkset
|
||||||
LinksetRoot.LocalID,
|
LinksetRoot.LocalID,
|
||||||
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
|
||||||
child.LocalID, child.BSBody.ptr.ToString("X"));
|
child.LocalID, child.BSBody.ptr.ToString("X"));
|
||||||
PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody);
|
PhysicallyLinkAChildToRoot(LinksetRoot, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,22 +342,22 @@ public class BSLinkset
|
||||||
{
|
{
|
||||||
m_children.Add(child);
|
m_children.Add(child);
|
||||||
|
|
||||||
BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
|
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||||
BulletBody rootBodyx = LinksetRoot.BSBody;
|
|
||||||
BSPhysObject childx = child;
|
BSPhysObject childx = child;
|
||||||
BulletBody childBodyx = child.BSBody;
|
|
||||||
|
|
||||||
DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
|
||||||
rootx.LocalID,
|
|
||||||
rootx.LocalID, rootBodyx.ptr.ToString("X"),
|
|
||||||
childx.LocalID, childBodyx.ptr.ToString("X"));
|
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
|
PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID);
|
DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}",
|
||||||
// build the physical binding between me and the child
|
rootx.LocalID,
|
||||||
m_taintChildren.Add(childx);
|
rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
|
||||||
PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx);
|
childx.LocalID, childx.BSBody.ptr.ToString("X"));
|
||||||
|
// Since this is taint-time, the body and shape could have changed for the child
|
||||||
|
rootx.ForcePosition = rootx.Position; // DEBUG
|
||||||
|
childx.ForcePosition = childx.Position; // DEBUG
|
||||||
|
PhysicallyLinkAChildToRoot(rootx, childx);
|
||||||
|
m_taintChildren.Add(child);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -369,21 +381,17 @@ public class BSLinkset
|
||||||
if (m_children.Remove(child))
|
if (m_children.Remove(child))
|
||||||
{
|
{
|
||||||
BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
|
BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
|
||||||
BulletBody rootBodyx = LinksetRoot.BSBody;
|
|
||||||
BSPhysObject childx = child;
|
BSPhysObject childx = child;
|
||||||
BulletBody childBodyx = child.BSBody;
|
|
||||||
|
|
||||||
DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
||||||
childx.LocalID,
|
childx.LocalID,
|
||||||
rootx.LocalID, rootBodyx.ptr.ToString("X"),
|
rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
|
||||||
childx.LocalID, childBodyx.ptr.ToString("X"));
|
childx.LocalID, childx.BSBody.ptr.ToString("X"));
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
||||||
{
|
{
|
||||||
if (m_taintChildren.Contains(childx))
|
m_taintChildren.Remove(child);
|
||||||
m_taintChildren.Remove(childx);
|
PhysicallyUnlinkAChildFromRoot(rootx, childx);
|
||||||
|
|
||||||
PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx);
|
|
||||||
RecomputeLinksetConstraintVariables();
|
RecomputeLinksetConstraintVariables();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -398,8 +406,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody,
|
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||||
BSPhysObject childPrim, BulletBody childBody)
|
|
||||||
{
|
{
|
||||||
// Zero motion for children so they don't interpolate
|
// Zero motion for children so they don't interpolate
|
||||||
childPrim.ZeroMotion();
|
childPrim.ZeroMotion();
|
||||||
|
@ -411,33 +418,17 @@ public class BSLinkset
|
||||||
// real world coordinate of midpoint between the two objects
|
// real world coordinate of midpoint between the two objects
|
||||||
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
|
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
|
||||||
|
|
||||||
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
|
DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
|
||||||
rootPrim.LocalID,
|
rootPrim.LocalID,
|
||||||
rootPrim.LocalID, rootBody.ptr.ToString("X"),
|
rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
|
||||||
childPrim.LocalID, childBody.ptr.ToString("X"),
|
childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"),
|
||||||
rootPrim.Position, childPrim.Position, midPoint);
|
rootPrim.Position, childPrim.Position, midPoint);
|
||||||
|
|
||||||
// create a constraint that allows no freedom of movement between the two objects
|
// create a constraint that allows no freedom of movement between the two objects
|
||||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||||
|
|
||||||
// There is great subtlty in these paramters. Notice the check for a ptr of zero.
|
|
||||||
// We pass the BulletBody structure into the taint in order to capture the pointer
|
|
||||||
// of the body at the time of constraint creation. This doesn't work for the very first
|
|
||||||
// construction because there is no body yet. The body
|
|
||||||
// is constructed later at taint time. Thus we use the body address at time of the
|
|
||||||
// taint creation but, if it is zero, use what's in the prim at the moment.
|
|
||||||
// There is a possible race condition since shape can change without a taint call
|
|
||||||
// (like changing to a mesh that is already constructed). The fix for that would be
|
|
||||||
// to only change BSShape at taint time thus syncronizing these operations at
|
|
||||||
// the cost of efficiency and lag.
|
|
||||||
BS6DofConstraint constrain = new BS6DofConstraint(
|
BS6DofConstraint constrain = new BS6DofConstraint(
|
||||||
PhysicsScene.World,
|
PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true );
|
||||||
rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody,
|
|
||||||
childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody,
|
|
||||||
midPoint,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
|
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
|
||||||
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
|
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
|
||||||
|
@ -454,7 +445,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// create a constraint that allows no freedom of movement between the two objects
|
// create a constraint that allows no freedom of movement between the two objects
|
||||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||||
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
||||||
BS6DofConstraint constrain = new BS6DofConstraint(
|
BS6DofConstraint constrain = new BS6DofConstraint(
|
||||||
PhysicsScene.World, rootPrim.Body, childPrim.Body,
|
PhysicsScene.World, rootPrim.Body, childPrim.Body,
|
||||||
OMV.Vector3.Zero,
|
OMV.Vector3.Zero,
|
||||||
|
@ -488,39 +479,44 @@ public class BSLinkset
|
||||||
{
|
{
|
||||||
constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
|
constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecomputeLinksetConstraintVariables();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove linkage between myself and a particular child
|
// Remove linkage between myself and a particular child
|
||||||
// The root and child bodies are passed in because we need to remove the constraint between
|
// The root and child bodies are passed in because we need to remove the constraint between
|
||||||
// the bodies that were at unlink time.
|
// the bodies that were at unlink time.
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody,
|
private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||||
BSPhysObject childPrim, BulletBody childBody)
|
|
||||||
{
|
{
|
||||||
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
|
bool ret = false;
|
||||||
|
DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
|
||||||
rootPrim.LocalID,
|
rootPrim.LocalID,
|
||||||
rootPrim.LocalID, rootBody.ptr.ToString("X"),
|
rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
|
||||||
childPrim.LocalID, childBody.ptr.ToString("X"));
|
childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"));
|
||||||
|
|
||||||
// Find the constraint for this link and get rid of it from the overall collection and from my list
|
// Find the constraint for this link and get rid of it from the overall collection and from my list
|
||||||
PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody);
|
if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody))
|
||||||
|
{
|
||||||
|
// Make the child refresh its location
|
||||||
|
BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Make the child refresh its location
|
return ret;
|
||||||
BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Remove linkage between myself and any possible children I might have.
|
// Remove linkage between myself and any possible children I might have.
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
||||||
{
|
{
|
||||||
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
|
if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody))
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// Call each of the constraints that make up this linkset and recompute the
|
// Call each of the constraints that make up this linkset and recompute the
|
||||||
// various transforms and variables. Used when objects are added or removed
|
// various transforms and variables. Used when objects are added or removed
|
||||||
|
@ -552,11 +548,17 @@ public class BSLinkset
|
||||||
{
|
{
|
||||||
// If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
|
// If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
|
||||||
OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
|
OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
|
||||||
BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
|
BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr,
|
||||||
|
centerOfMass, OMV.Quaternion.Identity);
|
||||||
|
DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}",
|
||||||
|
LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"));
|
||||||
foreach (BSPhysObject child in m_taintChildren)
|
foreach (BSPhysObject child in m_taintChildren)
|
||||||
{
|
{
|
||||||
BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity);
|
BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr,
|
||||||
|
centerOfMass, OMV.Quaternion.Identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -565,7 +567,8 @@ public class BSLinkset
|
||||||
// Invoke the detailed logger and output something if it's enabled.
|
// Invoke the detailed logger and output something if it's enabled.
|
||||||
private void DetailLog(string msg, params Object[] args)
|
private void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsScene.PhysicsLogging.Write(msg, args);
|
if (PhysicsScene.PhysicsLogging.Enabled)
|
||||||
|
PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,14 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// Tell the object to clean up.
|
// Tell the object to clean up.
|
||||||
public abstract void Destroy();
|
public abstract void Destroy();
|
||||||
|
|
||||||
|
public abstract OMV.Vector3 ForcePosition { get; set; }
|
||||||
|
|
||||||
|
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
||||||
|
|
||||||
|
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
||||||
|
|
||||||
|
public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
|
||||||
|
|
||||||
#region Collisions
|
#region Collisions
|
||||||
|
|
||||||
// Requested number of milliseconds between collision events. Zero means disabled.
|
// Requested number of milliseconds between collision events. Zero means disabled.
|
||||||
|
@ -203,7 +211,8 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// High performance detailed logging routine used by the physical objects.
|
// High performance detailed logging routine used by the physical objects.
|
||||||
protected void DetailLog(string msg, params Object[] args)
|
protected void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsScene.PhysicsLogging.Write(msg, args);
|
if (PhysicsScene.PhysicsLogging.Enabled)
|
||||||
|
PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,19 +46,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static readonly string LogHeader = "[BULLETS PRIM]";
|
private static readonly string LogHeader = "[BULLETS PRIM]";
|
||||||
|
|
||||||
private IMesh _mesh;
|
|
||||||
private PrimitiveBaseShape _pbs;
|
private PrimitiveBaseShape _pbs;
|
||||||
private ShapeData.PhysicsShapeType _shapeType;
|
|
||||||
private ulong _meshKey;
|
|
||||||
private ulong _hullKey;
|
|
||||||
private List<ConvexResult> _hulls;
|
|
||||||
|
|
||||||
// _size is what the user passed. _scale is what we pass to the physics engine with the mesh.
|
// _size is what the user passed. _scale is what we pass to the physics engine with the mesh.
|
||||||
// Often _scale is unity because the meshmerizer will apply _size when creating the mesh.
|
// Often _scale is unity because the meshmerizer will apply _size when creating the mesh.
|
||||||
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
|
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
|
||||||
private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
|
private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
|
||||||
|
|
||||||
private bool _stopped;
|
|
||||||
private bool _grabbed;
|
private bool _grabbed;
|
||||||
private bool _isSelected;
|
private bool _isSelected;
|
||||||
private bool _isVolumeDetect;
|
private bool _isVolumeDetect;
|
||||||
|
@ -109,8 +103,6 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_buoyancy = 1f;
|
_buoyancy = 1f;
|
||||||
_velocity = OMV.Vector3.Zero;
|
_velocity = OMV.Vector3.Zero;
|
||||||
_rotationalVelocity = OMV.Vector3.Zero;
|
_rotationalVelocity = OMV.Vector3.Zero;
|
||||||
_hullKey = 0;
|
|
||||||
_meshKey = 0;
|
|
||||||
_pbs = pbs;
|
_pbs = pbs;
|
||||||
_isPhysical = pisPhysical;
|
_isPhysical = pisPhysical;
|
||||||
_isVolumeDetect = false;
|
_isVolumeDetect = false;
|
||||||
|
@ -160,8 +152,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No one uses this property.
|
||||||
public override bool Stopped {
|
public override bool Stopped {
|
||||||
get { return _stopped; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 Size {
|
public override OMV.Vector3 Size {
|
||||||
get { return _size; }
|
get { return _size; }
|
||||||
|
@ -203,7 +196,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_isSelected = value;
|
_isSelected = value;
|
||||||
PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
|
DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
|
||||||
SetObjectDynamic(false);
|
SetObjectDynamic(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -272,8 +265,14 @@ public sealed class BSPrim : BSPhysObject
|
||||||
return _position;
|
return _position;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
|
// If you must push the position into the physics engine, use ForcePosition.
|
||||||
|
if (_position == value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
_position = value;
|
_position = value;
|
||||||
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
|
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
|
||||||
|
PositionSanityCheck();
|
||||||
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
|
||||||
{
|
{
|
||||||
// DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
// DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
@ -281,6 +280,74 @@ public sealed class BSPrim : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override OMV.Vector3 ForcePosition {
|
||||||
|
get {
|
||||||
|
_position = BulletSimAPI.GetPosition2(BSBody.ptr);
|
||||||
|
return _position;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_position = value;
|
||||||
|
PositionSanityCheck();
|
||||||
|
BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the current position is sane and, if not, modify the position to make it so.
|
||||||
|
// Check for being below terrain and being out of bounds.
|
||||||
|
// Returns 'true' of the position was made sane by some action.
|
||||||
|
private bool PositionSanityCheck()
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
// If totally below the ground, move the prim up
|
||||||
|
// TODO: figure out the right solution for this... only for dynamic objects?
|
||||||
|
/*
|
||||||
|
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||||
|
if (Position.Z < terrainHeight)
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
||||||
|
_position.Z = terrainHeight + 2.0f;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
|
||||||
|
{
|
||||||
|
float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
|
||||||
|
if (Position.Z < waterHeight)
|
||||||
|
{
|
||||||
|
_position.Z = waterHeight;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check for out of bounds
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A version of the sanity check that also makes sure a new position value is
|
||||||
|
// pushed back to the physics engine. This routine would be used by anyone
|
||||||
|
// who is not already pushing the value.
|
||||||
|
private bool PositionSanityCheck2(bool inTaintTime)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
if (PositionSanityCheck())
|
||||||
|
{
|
||||||
|
// The new position value must be pushed into the physics engine but we can't
|
||||||
|
// just assign to "Position" because of potential call loops.
|
||||||
|
BSScene.TaintCallback sanityOperation = delegate()
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
|
||||||
|
};
|
||||||
|
if (inTaintTime)
|
||||||
|
sanityOperation();
|
||||||
|
else
|
||||||
|
PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the effective mass of the object.
|
// Return the effective mass of the object.
|
||||||
// If there are multiple items in the linkset, add them together for the root
|
// If there are multiple items in the linkset, add them together for the root
|
||||||
|
@ -326,14 +393,15 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
Vehicle type = (Vehicle)value;
|
Vehicle type = (Vehicle)value;
|
||||||
BSPrim vehiclePrim = this;
|
|
||||||
|
// Tell the scene about the vehicle so it will get processing each frame.
|
||||||
|
PhysicsScene.VehicleInSceneTypeChanged(this, type);
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("setVehicleType", delegate()
|
PhysicsScene.TaintedObject("setVehicleType", delegate()
|
||||||
{
|
{
|
||||||
// Done at taint time so we're sure the physics engine is not using the variables
|
// Done at taint time so we're sure the physics engine is not using the variables
|
||||||
// Vehicle code changes the parameters for this vehicle type.
|
// Vehicle code changes the parameters for this vehicle type.
|
||||||
_vehicle.ProcessTypeChange(type);
|
this._vehicle.ProcessTypeChange(type);
|
||||||
// Tell the scene about the vehicle so it will get processing each frame.
|
|
||||||
PhysicsScene.VehicleInSceneTypeChanged(this, type);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,7 +439,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
public override void StepVehicle(float timeStep)
|
public override void StepVehicle(float timeStep)
|
||||||
{
|
{
|
||||||
if (IsPhysical)
|
if (IsPhysical)
|
||||||
|
{
|
||||||
_vehicle.Step(timeStep);
|
_vehicle.Step(timeStep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
|
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
|
||||||
|
@ -388,7 +458,6 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OMV.Vector3 Velocity {
|
public override OMV.Vector3 Velocity {
|
||||||
get { return _velocity; }
|
get { return _velocity; }
|
||||||
set {
|
set {
|
||||||
|
@ -400,6 +469,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override OMV.Vector3 ForceVelocity {
|
||||||
|
get { return _velocity; }
|
||||||
|
set {
|
||||||
|
_velocity = value;
|
||||||
|
BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
public override OMV.Vector3 Torque {
|
public override OMV.Vector3 Torque {
|
||||||
get { return _torque; }
|
get { return _torque; }
|
||||||
set { _torque = value;
|
set { _torque = value;
|
||||||
|
@ -425,6 +501,8 @@ public sealed class BSPrim : BSPhysObject
|
||||||
return _orientation;
|
return _orientation;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
|
if (_orientation == value)
|
||||||
|
return;
|
||||||
_orientation = value;
|
_orientation = value;
|
||||||
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
|
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
|
||||||
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
||||||
|
@ -435,6 +513,20 @@ public sealed class BSPrim : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Go directly to Bullet to get/set the value.
|
||||||
|
public override OMV.Quaternion ForceOrientation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
_orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
|
||||||
|
return _orientation;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_orientation = value;
|
||||||
|
BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
public override int PhysicsActorType {
|
public override int PhysicsActorType {
|
||||||
get { return _physicsActorType; }
|
get { return _physicsActorType; }
|
||||||
set { _physicsActorType = value; }
|
set { _physicsActorType = value; }
|
||||||
|
@ -488,11 +580,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
|
// This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
|
||||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
|
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
|
||||||
|
|
||||||
|
|
||||||
// Set up the object physicalness (does gravity and collisions move this object)
|
// Set up the object physicalness (does gravity and collisions move this object)
|
||||||
MakeDynamic(IsStatic);
|
MakeDynamic(IsStatic);
|
||||||
|
|
||||||
// Do any vehicle stuff
|
// Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
|
||||||
_vehicle.Refresh();
|
_vehicle.Refresh();
|
||||||
|
|
||||||
// Arrange for collision events if the simulator wants them
|
// Arrange for collision events if the simulator wants them
|
||||||
|
@ -515,7 +606,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// Recompute any linkset parameters.
|
// Recompute any linkset parameters.
|
||||||
// When going from non-physical to physical, this re-enables the constraints that
|
// When going from non-physical to physical, this re-enables the constraints that
|
||||||
// had been automatically disabled when the mass was set to zero.
|
// had been automatically disabled when the mass was set to zero.
|
||||||
Linkset.Refresh(this);
|
Linkset.Refresh(this, true);
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
|
DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
|
||||||
LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape);
|
LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape);
|
||||||
|
@ -542,8 +633,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
|
BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
|
||||||
// There can be special things needed for implementing linksets
|
// There can be special things needed for implementing linksets
|
||||||
Linkset.MakeStatic(this);
|
Linkset.MakeStatic(this);
|
||||||
// The activation state is 'disabled' so Bullet will not try to act on it
|
// The activation state is 'disabled' so Bullet will not try to act on it.
|
||||||
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
|
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
|
// Start it out sleeping and physical actions could wake it up.
|
||||||
|
// BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
|
||||||
|
|
||||||
BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
|
BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
|
||||||
BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
|
||||||
|
@ -560,10 +653,12 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
|
// per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
|
||||||
BulletSimAPI.ClearAllForces2(BSBody.ptr);
|
BulletSimAPI.ClearAllForces2(BSBody.ptr);
|
||||||
|
|
||||||
|
// For good measure, make sure the transform is set through to the motion state
|
||||||
|
BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
|
||||||
|
|
||||||
// A dynamic object has mass
|
// A dynamic object has mass
|
||||||
IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr);
|
IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr);
|
||||||
OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
|
OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
|
||||||
// OMV.Vector3 inertia = OMV.Vector3.Zero;
|
|
||||||
BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia);
|
BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia);
|
||||||
BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
|
BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
|
||||||
|
|
||||||
|
@ -573,13 +668,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
|
BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
|
||||||
BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
|
BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
|
||||||
|
|
||||||
// There can be special things needed for implementing linksets.
|
// There might be special things needed for implementing linksets.
|
||||||
Linkset.MakeDynamic(this);
|
Linkset.MakeDynamic(this);
|
||||||
|
|
||||||
// Force activation of the object so Bullet will act on it.
|
// Force activation of the object so Bullet will act on it.
|
||||||
// Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
|
// Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
|
||||||
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
|
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
|
||||||
BulletSimAPI.Activate2(BSBody.ptr, true);
|
// BulletSimAPI.Activate2(BSBody.ptr, true);
|
||||||
|
|
||||||
BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
|
BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
|
||||||
BSBody.collisionMask = CollisionFilterGroups.ObjectMask;
|
BSBody.collisionMask = CollisionFilterGroups.ObjectMask;
|
||||||
|
@ -663,7 +758,16 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override bool FloatOnWater {
|
public override bool FloatOnWater {
|
||||||
set { _floatOnWater = value; }
|
set {
|
||||||
|
_floatOnWater = value;
|
||||||
|
PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
|
||||||
|
{
|
||||||
|
if (_floatOnWater)
|
||||||
|
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
||||||
|
else
|
||||||
|
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public override OMV.Vector3 RotationalVelocity {
|
public override OMV.Vector3 RotationalVelocity {
|
||||||
get {
|
get {
|
||||||
|
@ -688,6 +792,15 @@ public sealed class BSPrim : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override OMV.Vector3 ForceRotationalVelocity {
|
||||||
|
get {
|
||||||
|
return _rotationalVelocity;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_rotationalVelocity = value;
|
||||||
|
BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
public override bool Kinematic {
|
public override bool Kinematic {
|
||||||
get { return _kinematic; }
|
get { return _kinematic; }
|
||||||
set { _kinematic = value;
|
set { _kinematic = value;
|
||||||
|
@ -742,6 +855,9 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
|
private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
|
||||||
public override void AddForce(OMV.Vector3 force, bool pushforce) {
|
public override void AddForce(OMV.Vector3 force, bool pushforce) {
|
||||||
|
AddForce(force, pushforce, false);
|
||||||
|
}
|
||||||
|
public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
|
||||||
// for an object, doesn't matter if force is a pushforce or not
|
// for an object, doesn't matter if force is a pushforce or not
|
||||||
if (force.IsFinite())
|
if (force.IsFinite())
|
||||||
{
|
{
|
||||||
|
@ -754,11 +870,12 @@ public sealed class BSPrim : BSPhysObject
|
||||||
m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
|
m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PhysicsScene.TaintedObject("BSPrim.AddForce", delegate()
|
BSScene.TaintCallback addForceOperation = delegate()
|
||||||
{
|
{
|
||||||
OMV.Vector3 fSum = OMV.Vector3.Zero;
|
OMV.Vector3 fSum = OMV.Vector3.Zero;
|
||||||
lock (m_accumulatedForces)
|
lock (m_accumulatedForces)
|
||||||
{
|
{
|
||||||
|
// Sum the accumulated additional forces for one big force to apply once.
|
||||||
foreach (OMV.Vector3 v in m_accumulatedForces)
|
foreach (OMV.Vector3 v in m_accumulatedForces)
|
||||||
{
|
{
|
||||||
fSum += v;
|
fSum += v;
|
||||||
|
@ -768,7 +885,11 @@ public sealed class BSPrim : BSPhysObject
|
||||||
// DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
|
// DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
|
||||||
// For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
|
// For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
|
||||||
BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum);
|
BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum);
|
||||||
});
|
};
|
||||||
|
if (inTaintTime)
|
||||||
|
addForceOperation();
|
||||||
|
else
|
||||||
|
PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
|
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
|
||||||
|
@ -1082,15 +1203,15 @@ public sealed class BSPrim : BSPhysObject
|
||||||
public void FillShapeInfo(out ShapeData shape)
|
public void FillShapeInfo(out ShapeData shape)
|
||||||
{
|
{
|
||||||
shape.ID = LocalID;
|
shape.ID = LocalID;
|
||||||
shape.Type = _shapeType;
|
shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
shape.Position = _position;
|
shape.Position = _position;
|
||||||
shape.Rotation = _orientation;
|
shape.Rotation = _orientation;
|
||||||
shape.Velocity = _velocity;
|
shape.Velocity = _velocity;
|
||||||
shape.Scale = _scale;
|
shape.Scale = _scale;
|
||||||
shape.Mass = _isPhysical ? _mass : 0f;
|
shape.Mass = _isPhysical ? _mass : 0f;
|
||||||
shape.Buoyancy = _buoyancy;
|
shape.Buoyancy = _buoyancy;
|
||||||
shape.HullKey = _hullKey;
|
shape.HullKey = 0;
|
||||||
shape.MeshKey = _meshKey;
|
shape.MeshKey = 0;
|
||||||
shape.Friction = _friction;
|
shape.Friction = _friction;
|
||||||
shape.Restitution = _restitution;
|
shape.Restitution = _restitution;
|
||||||
shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
|
shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
|
||||||
|
@ -1112,11 +1233,13 @@ public sealed class BSPrim : BSPhysObject
|
||||||
|
|
||||||
// Create the correct physical representation for this type of object.
|
// Create the correct physical representation for this type of object.
|
||||||
// Updates BSBody and BSShape with the new information.
|
// Updates BSBody and BSShape with the new information.
|
||||||
PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs,
|
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
|
||||||
|
PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs,
|
||||||
null, delegate(BulletBody dBody)
|
null, delegate(BulletBody dBody)
|
||||||
{
|
{
|
||||||
// Called if the current prim body is about to be destroyed.
|
// Called if the current prim body is about to be destroyed.
|
||||||
// Remove all the physical dependencies on the old body.
|
// Remove all the physical dependencies on the old body.
|
||||||
|
// (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
|
||||||
needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
|
needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1205,6 +1328,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
_rotationalVelocity = entprop.RotationalVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
|
||||||
|
PositionSanityCheck2(true);
|
||||||
|
|
||||||
|
Linkset.UpdateProperties(this);
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||||
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
|
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
|
||||||
|
|
||||||
|
@ -1215,7 +1342,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
/*
|
/*
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// For debugging, we can also report the movement of children
|
// For debugging, report the movement of children
|
||||||
DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||||
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
||||||
entprop.Acceleration, entprop.RotationalVelocity);
|
entprop.Acceleration, entprop.RotationalVelocity);
|
||||||
|
|
|
@ -39,7 +39,6 @@ using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
|
||||||
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
|
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
|
||||||
// Move all logic out of the C++ code and into the C# code for easier future modifications.
|
|
||||||
// Test sculpties (verified that they don't work)
|
// Test sculpties (verified that they don't work)
|
||||||
// Compute physics FPS reasonably
|
// Compute physics FPS reasonably
|
||||||
// Based on material, set density and friction
|
// Based on material, set density and friction
|
||||||
|
@ -90,10 +89,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// let my minuions use my logger
|
// let my minuions use my logger
|
||||||
public ILog Logger { get { return m_log; } }
|
public ILog Logger { get { return m_log; } }
|
||||||
|
|
||||||
// If non-zero, the number of simulation steps between calls to the physics
|
|
||||||
// engine to output detailed physics stats. Debug logging level must be on also.
|
|
||||||
private int m_detailedStatsStep = 0;
|
|
||||||
|
|
||||||
public IMesher mesher;
|
public IMesher mesher;
|
||||||
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
||||||
public float MeshLOD { get; private set; }
|
public float MeshLOD { get; private set; }
|
||||||
|
@ -112,6 +107,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
private float m_fixedTimeStep;
|
private float m_fixedTimeStep;
|
||||||
private long m_simulationStep = 0;
|
private long m_simulationStep = 0;
|
||||||
public long SimulationStep { get { return m_simulationStep; } }
|
public long SimulationStep { get { return m_simulationStep; } }
|
||||||
|
private int m_taintsToProcessPerStep;
|
||||||
|
|
||||||
// A value of the time now so all the collision and update routines do not have to get their own
|
// A value of the time now so all the collision and update routines do not have to get their own
|
||||||
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||||
|
@ -131,6 +127,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
|
public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
|
||||||
public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
|
public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
|
||||||
|
public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
|
||||||
|
|
||||||
public float PID_D { get; private set; } // derivative
|
public float PID_D { get; private set; } // derivative
|
||||||
public float PID_P { get; private set; } // proportional
|
public float PID_P { get; private set; } // proportional
|
||||||
|
@ -254,7 +251,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
// The bounding box for the simulated world. The origin is 0,0,0 unless we're
|
// The bounding box for the simulated world. The origin is 0,0,0 unless we're
|
||||||
// a child in a mega-region.
|
// a child in a mega-region.
|
||||||
// Turns out that Bullet really doesn't care about the extents of the simulated
|
// Bullet actually doesn't care about the extents of the simulated
|
||||||
// area. It tracks active objects no matter where they are.
|
// area. It tracks active objects no matter where they are.
|
||||||
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
||||||
|
|
||||||
|
@ -331,7 +328,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// Called directly from unmanaged code so don't do much
|
// Called directly from unmanaged code so don't do much
|
||||||
private void BulletLoggerPhysLog(string msg)
|
private void BulletLoggerPhysLog(string msg)
|
||||||
{
|
{
|
||||||
PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
|
DetailLog("[BULLETS UNMANAGED]:" + msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
|
@ -493,6 +490,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// step the physical world one interval
|
// step the physical world one interval
|
||||||
m_simulationStep++;
|
m_simulationStep++;
|
||||||
int numSubSteps = 0;
|
int numSubSteps = 0;
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
// DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
|
||||||
|
@ -501,8 +502,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
||||||
|
|
||||||
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
||||||
DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}",
|
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
|
||||||
DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -536,7 +537,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a kludge to get avatar movement updates.
|
// This is a kludge to get avatar movement updates.
|
||||||
// ODE sends collisions for avatars even if there are have been no collisions. This updates
|
// the simulator expects collisions for avatars even if there are have been no collisions. This updates
|
||||||
// avatar animations and stuff.
|
// avatar animations and stuff.
|
||||||
// If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
|
// If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
|
||||||
foreach (BSPhysObject bsp in m_avatars)
|
foreach (BSPhysObject bsp in m_avatars)
|
||||||
|
@ -556,7 +557,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// Objects that are done colliding are removed from the ObjectsWithCollisions list.
|
// Objects that are done colliding are removed from the ObjectsWithCollisions list.
|
||||||
// This can't be done by SendCollisions because it is inside an iteration of ObjectWithCollisions.
|
// Not done above because it is inside an iteration of ObjectWithCollisions.
|
||||||
if (ObjectsWithNoMoreCollisions.Count > 0)
|
if (ObjectsWithNoMoreCollisions.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
|
foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
|
||||||
|
@ -578,19 +579,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If enabled, call into the physics engine to dump statistics
|
|
||||||
if (m_detailedStatsStep > 0)
|
|
||||||
{
|
|
||||||
if ((m_simulationStep % m_detailedStatsStep) == 0)
|
|
||||||
{
|
|
||||||
BulletSimAPI.DumpBulletStatistics();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The physics engine returns the number of milliseconds it simulated this call.
|
// The physics engine returns the number of milliseconds it simulated this call.
|
||||||
// These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
|
// These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
|
||||||
// Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS.
|
// We multiply by 45 to give a recognizable running rate (45 or less).
|
||||||
return numSubSteps * m_fixedTimeStep * 1000;
|
return numSubSteps * m_fixedTimeStep * 1000 * 45;
|
||||||
|
// return timeStep * 1000 * 45;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Something has collided
|
// Something has collided
|
||||||
|
@ -613,7 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
BSPhysObject collidee = null;
|
BSPhysObject collidee = null;
|
||||||
PhysObjects.TryGetValue(collidingWith, out collidee);
|
PhysObjects.TryGetValue(collidingWith, out collidee);
|
||||||
|
|
||||||
DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
|
// DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
|
||||||
|
|
||||||
if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
|
if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
|
||||||
{
|
{
|
||||||
|
@ -699,6 +692,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
|
if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
|
||||||
{
|
{
|
||||||
|
// swizzle a new list into the list location so we can process what's there
|
||||||
|
int taintCount = m_taintsToProcessPerStep;
|
||||||
|
TaintCallbackEntry oneCallback = new TaintCallbackEntry();
|
||||||
|
while (_taintedObjects.Count > 0 && taintCount-- > 0)
|
||||||
|
{
|
||||||
|
bool gotOne = false;
|
||||||
|
lock (_taintLock)
|
||||||
|
{
|
||||||
|
if (_taintedObjects.Count > 0)
|
||||||
|
{
|
||||||
|
oneCallback = _taintedObjects[0];
|
||||||
|
_taintedObjects.RemoveAt(0);
|
||||||
|
gotOne = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gotOne)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
|
||||||
|
oneCallback.callback();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
// swizzle a new list into the list location so we can process what's there
|
// swizzle a new list into the list location so we can process what's there
|
||||||
List<TaintCallbackEntry> oldList;
|
List<TaintCallbackEntry> oldList;
|
||||||
lock (_taintLock)
|
lock (_taintLock)
|
||||||
|
@ -711,6 +733,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
|
||||||
tcbe.callback();
|
tcbe.callback();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -719,6 +742,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oldList.Clear();
|
oldList.Clear();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,13 +750,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
|
public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
|
||||||
{
|
{
|
||||||
if (newType == Vehicle.TYPE_NONE)
|
RemoveVehiclePrim(vehic);
|
||||||
|
if (newType != Vehicle.TYPE_NONE)
|
||||||
{
|
{
|
||||||
RemoveVehiclePrim(vehic);
|
// make it so the scene will call us each tick to do vehicle things
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// make it so the scene will call us each tick to do vehicle things
|
|
||||||
AddVehiclePrim(vehic);
|
AddVehiclePrim(vehic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,7 +785,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some prims have extra vehicle actions
|
// Some prims have extra vehicle actions
|
||||||
// no locking because only called when physics engine is not busy
|
// Called at taint time!
|
||||||
private void ProcessVehicles(float timeStep)
|
private void ProcessVehicles(float timeStep)
|
||||||
{
|
{
|
||||||
foreach (BSPhysObject pobj in m_vehicles)
|
foreach (BSPhysObject pobj in m_vehicles)
|
||||||
|
@ -833,6 +854,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
(s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||||
(s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
|
(s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
|
||||||
(s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
|
(s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
|
||||||
|
new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
|
||||||
|
ConfigurationParameters.numericTrue,
|
||||||
|
(s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||||
|
(s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
|
||||||
|
(s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
|
||||||
|
|
||||||
new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
||||||
8f,
|
8f,
|
||||||
|
@ -875,6 +901,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
|
(s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
|
||||||
(s) => { return (float)s.m_maxUpdatesPerFrame; },
|
(s) => { return (float)s.m_maxUpdatesPerFrame; },
|
||||||
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
||||||
|
new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
|
||||||
|
100f,
|
||||||
|
(s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
|
||||||
|
(s) => { return (float)s.m_taintsToProcessPerStep; },
|
||||||
|
(s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
|
||||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||||
10000.01f,
|
10000.01f,
|
||||||
(s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
|
||||||
|
@ -1008,12 +1039,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
|
|
||||||
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
||||||
0f, // zero to disable
|
0f,
|
||||||
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
|
(s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
|
||||||
(s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
|
(s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
|
||||||
new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
|
new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
|
||||||
0f, // zero to disable
|
0f,
|
||||||
(s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
|
(s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
|
||||||
(s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
|
(s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
|
||||||
|
@ -1028,7 +1059,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
|
(s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
|
||||||
(s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
|
(s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
|
||||||
new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
|
new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
|
||||||
ConfigurationParameters.numericFalse,
|
ConfigurationParameters.numericTrue,
|
||||||
(s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
|
(s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
|
||||||
(s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
|
(s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
|
||||||
(s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
|
(s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
|
||||||
|
@ -1069,12 +1100,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
|
(s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
|
||||||
(s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
|
(s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
|
||||||
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
|
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
|
||||||
0.1f,
|
0.001f,
|
||||||
(s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].linkConstraintCFM; },
|
(s) => { return s.m_params[0].linkConstraintCFM; },
|
||||||
(s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
|
(s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
|
||||||
new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
|
new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
|
||||||
0.2f,
|
0.8f,
|
||||||
(s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].linkConstraintERP; },
|
(s) => { return s.m_params[0].linkConstraintERP; },
|
||||||
(s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
|
(s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
|
||||||
|
@ -1084,11 +1115,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s) => { return s.m_params[0].linkConstraintSolverIterations; },
|
(s) => { return s.m_params[0].linkConstraintSolverIterations; },
|
||||||
(s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
|
(s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
|
new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
|
(s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
|
||||||
(s) => { return (float)s.m_detailedStatsStep; },
|
(s) => { return (float)s.m_params[0].physicsLoggingFrames; },
|
||||||
(s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
|
(s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert a boolean to our numeric true and false values
|
// Convert a boolean to our numeric true and false values
|
||||||
|
@ -1152,7 +1183,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
if (SettableParameters.Length < ParameterDefinitions.Length)
|
if (SettableParameters.Length < ParameterDefinitions.Length)
|
||||||
{
|
{
|
||||||
|
|
||||||
List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
|
List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
|
||||||
for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
|
for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
|
||||||
{
|
{
|
||||||
|
@ -1270,6 +1300,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
public void DetailLog(string msg, params Object[] args)
|
public void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsLogging.Write(msg, args);
|
PhysicsLogging.Write(msg, args);
|
||||||
|
// Add the Flush() if debugging crashes to get all the messages written out.
|
||||||
|
// PhysicsLogging.Flush();
|
||||||
}
|
}
|
||||||
// used to fill in the LocalID when there isn't one
|
// used to fill in the LocalID when there isn't one
|
||||||
public const string DetailLogZero = "0000000000";
|
public const string DetailLogZero = "0000000000";
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
public class BSShapeCollection : IDisposable
|
public class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
|
// private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
|
||||||
|
|
||||||
protected BSScene PhysicsScene { get; set; }
|
protected BSScene PhysicsScene { get; set; }
|
||||||
|
|
||||||
|
@ -67,8 +67,8 @@ public class BSShapeCollection : IDisposable
|
||||||
public DateTime lastReferenced;
|
public DateTime lastReferenced;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>();
|
private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
|
||||||
private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>();
|
private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
|
||||||
private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>();
|
private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>();
|
||||||
|
|
||||||
public BSShapeCollection(BSScene physScene)
|
public BSShapeCollection(BSScene physScene)
|
||||||
|
@ -108,7 +108,8 @@ public class BSShapeCollection : IDisposable
|
||||||
// If we had to select a new shape geometry for the object,
|
// If we had to select a new shape geometry for the object,
|
||||||
// rebuild the body around it.
|
// rebuild the body around it.
|
||||||
// Updates prim.BSBody with information/pointers to requested body
|
// Updates prim.BSBody with information/pointers to requested body
|
||||||
bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback);
|
bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World,
|
||||||
|
prim.BSShape, shapeData, bodyCallback);
|
||||||
ret = newGeom || newBody;
|
ret = newGeom || newBody;
|
||||||
}
|
}
|
||||||
DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}",
|
DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}",
|
||||||
|
@ -120,7 +121,7 @@ public class BSShapeCollection : IDisposable
|
||||||
// Track another user of a body
|
// Track another user of a body
|
||||||
// We presume the caller has allocated the body.
|
// We presume the caller has allocated the body.
|
||||||
// Bodies only have one user so the reference count is either 1 or 0.
|
// Bodies only have one user so the reference count is either 1 or 0.
|
||||||
public void ReferenceBody(BulletBody body, bool atTaintTime)
|
public void ReferenceBody(BulletBody body, bool inTaintTime)
|
||||||
{
|
{
|
||||||
lock (m_collectionActivityLock)
|
lock (m_collectionActivityLock)
|
||||||
{
|
{
|
||||||
|
@ -135,12 +136,26 @@ public class BSShapeCollection : IDisposable
|
||||||
// New entry
|
// New entry
|
||||||
bodyDesc.ptr = body.ptr;
|
bodyDesc.ptr = body.ptr;
|
||||||
bodyDesc.referenceCount = 1;
|
bodyDesc.referenceCount = 1;
|
||||||
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", body.ID, body, bodyDesc.referenceCount);
|
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}",
|
||||||
|
body.ID, body, bodyDesc.referenceCount);
|
||||||
|
BSScene.TaintCallback createOperation = delegate()
|
||||||
|
{
|
||||||
|
if (!BulletSimAPI.IsInWorld2(body.ptr))
|
||||||
|
{
|
||||||
|
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
|
||||||
|
DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}",
|
||||||
|
body.ID, body);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (inTaintTime)
|
||||||
|
createOperation();
|
||||||
|
else
|
||||||
|
PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
|
||||||
}
|
}
|
||||||
bodyDesc.lastReferenced = System.DateTime.Now;
|
bodyDesc.lastReferenced = System.DateTime.Now;
|
||||||
Bodies[body.ID] = bodyDesc;
|
Bodies[body.ID] = bodyDesc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the usage of a body.
|
// Release the usage of a body.
|
||||||
// Called when releasing use of a BSBody. BSShape is handled separately.
|
// Called when releasing use of a BSBody. BSShape is handled separately.
|
||||||
|
@ -159,21 +174,22 @@ public class BSShapeCollection : IDisposable
|
||||||
Bodies[body.ID] = bodyDesc;
|
Bodies[body.ID] = bodyDesc;
|
||||||
DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount);
|
DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount);
|
||||||
|
|
||||||
// If body is no longer being used, free it -- bodies are never shared.
|
// If body is no longer being used, free it -- bodies can never be shared.
|
||||||
if (bodyDesc.referenceCount == 0)
|
if (bodyDesc.referenceCount == 0)
|
||||||
{
|
{
|
||||||
Bodies.Remove(body.ID);
|
Bodies.Remove(body.ID);
|
||||||
BSScene.TaintCallback removeOperation = delegate()
|
BSScene.TaintCallback removeOperation = delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}",
|
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}",
|
||||||
body.ID, body.ptr.ToString("X"));
|
body.ID, body.ptr.ToString("X"), inTaintTime);
|
||||||
// If the caller needs to know, pass the event up.
|
// If the caller needs to know the old body is going away, pass the event up.
|
||||||
if (bodyCallback != null) bodyCallback(body);
|
if (bodyCallback != null) bodyCallback(body);
|
||||||
|
|
||||||
|
// It may have already been removed from the world in which case the next is a NOOP.
|
||||||
|
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
|
||||||
|
|
||||||
// Zero any reference to the shape so it is not freed when the body is deleted.
|
// Zero any reference to the shape so it is not freed when the body is deleted.
|
||||||
BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
|
BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
|
||||||
// It may have already been removed from the world in which case the next is a NOOP.
|
|
||||||
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
|
|
||||||
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
|
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
|
||||||
};
|
};
|
||||||
// If already in taint-time, do the operations now. Otherwise queue for later.
|
// If already in taint-time, do the operations now. Otherwise queue for later.
|
||||||
|
@ -207,7 +223,7 @@ public class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
// There is an existing instance of this mesh.
|
// There is an existing instance of this mesh.
|
||||||
meshDesc.referenceCount++;
|
meshDesc.referenceCount++;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -216,7 +232,7 @@ public class BSShapeCollection : IDisposable
|
||||||
meshDesc.ptr = shape.ptr;
|
meshDesc.ptr = shape.ptr;
|
||||||
// We keep a reference to the underlying IMesh data so a hull can be built
|
// We keep a reference to the underlying IMesh data so a hull can be built
|
||||||
meshDesc.referenceCount = 1;
|
meshDesc.referenceCount = 1;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +245,7 @@ public class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
// There is an existing instance of this hull.
|
// There is an existing instance of this hull.
|
||||||
hullDesc.referenceCount++;
|
hullDesc.referenceCount++;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -237,7 +253,7 @@ public class BSShapeCollection : IDisposable
|
||||||
// This is a new reference to a hull
|
// This is a new reference to a hull
|
||||||
hullDesc.ptr = shape.ptr;
|
hullDesc.ptr = shape.ptr;
|
||||||
hullDesc.referenceCount = 1;
|
hullDesc.referenceCount = 1;
|
||||||
DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}",
|
DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
|
||||||
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
|
@ -256,7 +272,7 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
// Release the usage of a shape.
|
// Release the usage of a shape.
|
||||||
// The collisionObject is released since it is a copy of the real collision shape.
|
// The collisionObject is released since it is a copy of the real collision shape.
|
||||||
public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback)
|
public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
|
||||||
{
|
{
|
||||||
if (shape.ptr == IntPtr.Zero)
|
if (shape.ptr == IntPtr.Zero)
|
||||||
return;
|
return;
|
||||||
|
@ -278,14 +294,14 @@ public class BSShapeCollection : IDisposable
|
||||||
if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
|
if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
|
DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
|
||||||
BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime);
|
BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
|
||||||
if (shapeCallback != null) shapeCallback(shape);
|
if (shapeCallback != null) shapeCallback(shape);
|
||||||
BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
|
BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (atTaintTime)
|
if (inTaintTime)
|
||||||
{
|
{
|
||||||
lock (m_collectionActivityLock)
|
lock (m_collectionActivityLock)
|
||||||
{
|
{
|
||||||
|
@ -357,7 +373,8 @@ public class BSShapeCollection : IDisposable
|
||||||
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
|
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
|
||||||
&& pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
|
&& pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
|
||||||
{
|
{
|
||||||
if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
|
if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||||
|
&& pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
|
||||||
{
|
{
|
||||||
haveShape = true;
|
haveShape = true;
|
||||||
if (forceRebuild
|
if (forceRebuild
|
||||||
|
@ -371,7 +388,7 @@ public class BSShapeCollection : IDisposable
|
||||||
prim.LocalID, forceRebuild, prim.BSShape);
|
prim.LocalID, forceRebuild, prim.BSShape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
|
||||||
{
|
{
|
||||||
haveShape = true;
|
haveShape = true;
|
||||||
if (forceRebuild
|
if (forceRebuild
|
||||||
|
@ -391,7 +408,7 @@ public class BSShapeCollection : IDisposable
|
||||||
// made. Native shapes are best used in either case.
|
// made. Native shapes are best used in either case.
|
||||||
if (!haveShape)
|
if (!haveShape)
|
||||||
{
|
{
|
||||||
if (prim.IsPhysical)
|
if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
|
||||||
{
|
{
|
||||||
// Update prim.BSShape to reference a hull of this shape.
|
// Update prim.BSShape to reference a hull of this shape.
|
||||||
ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback);
|
ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback);
|
||||||
|
@ -425,7 +442,7 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
// Native shapes are always built independently.
|
// Native shapes are always built independently.
|
||||||
newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
|
newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
|
||||||
newShape.shapeKey = (ulong)shapeKey;
|
newShape.shapeKey = (System.UInt64)shapeKey;
|
||||||
newShape.isNativeShape = true;
|
newShape.isNativeShape = true;
|
||||||
|
|
||||||
// Don't need to do a 'ReferenceShape()' here because native shapes are not tracked.
|
// Don't need to do a 'ReferenceShape()' here because native shapes are not tracked.
|
||||||
|
@ -445,10 +462,11 @@ public class BSShapeCollection : IDisposable
|
||||||
BulletShape newShape = new BulletShape(IntPtr.Zero);
|
BulletShape newShape = new BulletShape(IntPtr.Zero);
|
||||||
|
|
||||||
float lod;
|
float lod;
|
||||||
ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);
|
System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);
|
||||||
|
|
||||||
// if this new shape is the same as last time, don't recreate the mesh
|
// if this new shape is the same as last time, don't recreate the mesh
|
||||||
if (prim.BSShape.shapeKey == newMeshKey) return false;
|
if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
|
||||||
|
return false;
|
||||||
|
|
||||||
DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}",
|
DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}",
|
||||||
prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
|
prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
|
||||||
|
@ -467,7 +485,7 @@ public class BSShapeCollection : IDisposable
|
||||||
return true; // 'true' means a new shape has been added to this prim
|
return true; // 'true' means a new shape has been added to this prim
|
||||||
}
|
}
|
||||||
|
|
||||||
private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||||
{
|
{
|
||||||
IMesh meshData = null;
|
IMesh meshData = null;
|
||||||
IntPtr meshPtr;
|
IntPtr meshPtr;
|
||||||
|
@ -514,7 +532,7 @@ public class BSShapeCollection : IDisposable
|
||||||
BulletShape newShape;
|
BulletShape newShape;
|
||||||
|
|
||||||
float lod;
|
float lod;
|
||||||
ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod);
|
System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod);
|
||||||
|
|
||||||
// if the hull hasn't changed, don't rebuild it
|
// if the hull hasn't changed, don't rebuild it
|
||||||
if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
|
if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
|
||||||
|
@ -523,7 +541,7 @@ public class BSShapeCollection : IDisposable
|
||||||
DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
|
DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
|
||||||
prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
|
prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
|
||||||
|
|
||||||
// Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull.
|
// Remove usage of the previous shape.
|
||||||
DereferenceShape(prim.BSShape, true, shapeCallback);
|
DereferenceShape(prim.BSShape, true, shapeCallback);
|
||||||
|
|
||||||
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
|
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
|
||||||
|
@ -537,7 +555,7 @@ public class BSShapeCollection : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ConvexResult> m_hulls;
|
List<ConvexResult> m_hulls;
|
||||||
private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
|
||||||
{
|
{
|
||||||
|
|
||||||
IntPtr hullPtr;
|
IntPtr hullPtr;
|
||||||
|
@ -650,22 +668,23 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
// Create a hash of all the shape parameters to be used as a key
|
// Create a hash of all the shape parameters to be used as a key
|
||||||
// for this particular shape.
|
// for this particular shape.
|
||||||
private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod)
|
private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod)
|
||||||
{
|
{
|
||||||
// level of detail based on size and type of the object
|
// level of detail based on size and type of the object
|
||||||
float lod = PhysicsScene.MeshLOD;
|
float lod = PhysicsScene.MeshLOD;
|
||||||
if (pbs.SculptEntry)
|
if (pbs.SculptEntry)
|
||||||
lod = PhysicsScene.SculptLOD;
|
lod = PhysicsScene.SculptLOD;
|
||||||
|
|
||||||
|
// Mega prims usually get more detail because one can interact with shape approximations at this size.
|
||||||
float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
|
float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
|
||||||
if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
|
if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
|
||||||
lod = PhysicsScene.MeshMegaPrimLOD;
|
lod = PhysicsScene.MeshMegaPrimLOD;
|
||||||
|
|
||||||
retLod = lod;
|
retLod = lod;
|
||||||
return (ulong)pbs.GetMeshKey(shapeData.Size, lod);
|
return pbs.GetMeshKey(shapeData.Size, lod);
|
||||||
}
|
}
|
||||||
// For those who don't want the LOD
|
// For those who don't want the LOD
|
||||||
private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs)
|
private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs)
|
||||||
{
|
{
|
||||||
float lod;
|
float lod;
|
||||||
return ComputeShapeKey(shapeData, pbs, out lod);
|
return ComputeShapeKey(shapeData, pbs, out lod);
|
||||||
|
@ -699,6 +718,7 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
if (mustRebuild || forceRebuild)
|
if (mustRebuild || forceRebuild)
|
||||||
{
|
{
|
||||||
|
// Free any old body
|
||||||
DereferenceBody(prim.BSBody, true, bodyCallback);
|
DereferenceBody(prim.BSBody, true, bodyCallback);
|
||||||
|
|
||||||
BulletBody aBody;
|
BulletBody aBody;
|
||||||
|
@ -707,13 +727,13 @@ public class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
|
bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
|
||||||
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
||||||
// DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
|
bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
|
||||||
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
shapeData.ID, shapeData.Position, shapeData.Rotation);
|
||||||
// DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
|
||||||
}
|
}
|
||||||
aBody = new BulletBody(shapeData.ID, bodyPtr);
|
aBody = new BulletBody(shapeData.ID, bodyPtr);
|
||||||
|
|
||||||
|
@ -729,7 +749,8 @@ public class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
private void DetailLog(string msg, params Object[] args)
|
private void DetailLog(string msg, params Object[] args)
|
||||||
{
|
{
|
||||||
PhysicsScene.PhysicsLogging.Write(msg, args);
|
if (PhysicsScene.PhysicsLogging.Enabled)
|
||||||
|
PhysicsScene.DetailLog(msg, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,8 @@ public class BSTerrainManager
|
||||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
|
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
|
||||||
Vector3.Zero, Quaternion.Identity));
|
Vector3.Zero, Quaternion.Identity));
|
||||||
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
|
||||||
|
// Ground plane does not move
|
||||||
|
BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
|
||||||
// Everything collides with the ground plane.
|
// Everything collides with the ground plane.
|
||||||
BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
|
BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
|
||||||
(uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
|
(uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
|
||||||
|
@ -201,10 +203,10 @@ public class BSTerrainManager
|
||||||
// The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
|
// The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
|
||||||
// calling this routine from initialization or taint-time routines) or whether to delay
|
// calling this routine from initialization or taint-time routines) or whether to delay
|
||||||
// all the unmanaged activities to taint-time.
|
// all the unmanaged activities to taint-time.
|
||||||
private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool atTaintTime)
|
private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},atTaintTime={3}",
|
DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
|
||||||
BSScene.DetailLogZero, minCoords, maxCoords, atTaintTime);
|
BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
|
||||||
|
|
||||||
float minZ = float.MaxValue;
|
float minZ = float.MaxValue;
|
||||||
float maxZ = float.MinValue;
|
float maxZ = float.MinValue;
|
||||||
|
@ -296,16 +298,16 @@ public class BSTerrainManager
|
||||||
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID,
|
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID,
|
||||||
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||||
|
|
||||||
|
// Create the terrain shape from the mapInfo
|
||||||
|
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
|
||||||
|
ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
|
||||||
|
|
||||||
// The terrain object initial position is at the center of the object
|
// The terrain object initial position is at the center of the object
|
||||||
Vector3 centerPos;
|
Vector3 centerPos;
|
||||||
centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
|
centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
|
||||||
centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
|
centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
|
||||||
centerPos.Z = minZ + ((maxZ - minZ) / 2f);
|
centerPos.Z = minZ + ((maxZ - minZ) / 2f);
|
||||||
|
|
||||||
// Create the terrain shape from the mapInfo
|
|
||||||
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
|
|
||||||
ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
|
|
||||||
|
|
||||||
mapInfo.terrainBody = new BulletBody(mapInfo.ID,
|
mapInfo.terrainBody = new BulletBody(mapInfo.ID,
|
||||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
|
BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
|
||||||
id, centerPos, Quaternion.Identity));
|
id, centerPos, Quaternion.Identity));
|
||||||
|
@ -320,9 +322,6 @@ public class BSTerrainManager
|
||||||
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
|
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
|
||||||
BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
|
BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||||
|
|
||||||
BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, 0f, Vector3.Zero);
|
|
||||||
BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr);
|
|
||||||
|
|
||||||
// Return the new terrain to the world of physical objects
|
// Return the new terrain to the world of physical objects
|
||||||
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
|
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
|
||||||
|
|
||||||
|
@ -342,7 +341,7 @@ public class BSTerrainManager
|
||||||
|
|
||||||
// There is the option to do the changes now (we're already in 'taint time'), or
|
// There is the option to do the changes now (we're already in 'taint time'), or
|
||||||
// to do the Bullet operations later.
|
// to do the Bullet operations later.
|
||||||
if (atTaintTime)
|
if (inTaintTime)
|
||||||
rebuildOperation();
|
rebuildOperation();
|
||||||
else
|
else
|
||||||
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
|
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
|
||||||
|
@ -381,7 +380,7 @@ public class BSTerrainManager
|
||||||
};
|
};
|
||||||
|
|
||||||
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
|
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
|
||||||
if (atTaintTime)
|
if (inTaintTime)
|
||||||
createOperation();
|
createOperation();
|
||||||
else
|
else
|
||||||
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
|
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
|
||||||
|
|
|
@ -71,7 +71,7 @@ public struct BulletBody
|
||||||
buff.Append(ID.ToString());
|
buff.Append(ID.ToString());
|
||||||
buff.Append(",p=");
|
buff.Append(",p=");
|
||||||
buff.Append(ptr.ToString("X"));
|
buff.Append(ptr.ToString("X"));
|
||||||
if (collisionFilter != 0 && collisionMask != 0)
|
if (collisionFilter != 0 || collisionMask != 0)
|
||||||
{
|
{
|
||||||
buff.Append(",f=");
|
buff.Append(",f=");
|
||||||
buff.Append(collisionFilter.ToString("X"));
|
buff.Append(collisionFilter.ToString("X"));
|
||||||
|
@ -101,9 +101,8 @@ public struct BulletShape
|
||||||
}
|
}
|
||||||
public IntPtr ptr;
|
public IntPtr ptr;
|
||||||
public ShapeData.PhysicsShapeType type;
|
public ShapeData.PhysicsShapeType type;
|
||||||
public ulong shapeKey;
|
public System.UInt64 shapeKey;
|
||||||
public bool isNativeShape;
|
public bool isNativeShape;
|
||||||
// Hulls have an underlying mesh. A pointer to it is hidden here.
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
StringBuilder buff = new StringBuilder();
|
StringBuilder buff = new StringBuilder();
|
||||||
|
@ -192,8 +191,9 @@ public struct ShapeData
|
||||||
SHAPE_SPHERE = 5,
|
SHAPE_SPHERE = 5,
|
||||||
SHAPE_MESH = 6,
|
SHAPE_MESH = 6,
|
||||||
SHAPE_HULL = 7,
|
SHAPE_HULL = 7,
|
||||||
SHAPE_GROUNDPLANE = 8,
|
// following defined by BulletSim
|
||||||
SHAPE_TERRAIN = 9,
|
SHAPE_GROUNDPLANE = 20,
|
||||||
|
SHAPE_TERRAIN = 21,
|
||||||
};
|
};
|
||||||
public uint ID;
|
public uint ID;
|
||||||
public PhysicsShapeType Type;
|
public PhysicsShapeType Type;
|
||||||
|
@ -305,6 +305,8 @@ public struct ConfigurationParameters
|
||||||
public float linkConstraintCFM;
|
public float linkConstraintCFM;
|
||||||
public float linkConstraintSolverIterations;
|
public float linkConstraintSolverIterations;
|
||||||
|
|
||||||
|
public float physicsLoggingFrames;
|
||||||
|
|
||||||
public const float numericTrue = 1f;
|
public const float numericTrue = 1f;
|
||||||
public const float numericFalse = 0f;
|
public const float numericFalse = 0f;
|
||||||
}
|
}
|
||||||
|
@ -344,10 +346,7 @@ public enum CollisionFlags : uint
|
||||||
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
|
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
|
||||||
// Following used by BulletSim to control collisions
|
// Following used by BulletSim to control collisions
|
||||||
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
|
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
|
||||||
// BS_VOLUME_DETECT_OBJECT = 1 << 11,
|
BS_FLOATS_ON_WATER = 1 << 11,
|
||||||
// BS_PHANTOM_OBJECT = 1 << 12,
|
|
||||||
// BS_PHYSICAL_OBJECT = 1 << 13,
|
|
||||||
// BS_TERRAIN_OBJECT = 1 << 14,
|
|
||||||
BS_NONE = 0,
|
BS_NONE = 0,
|
||||||
BS_ALL = 0xFFFFFFFF,
|
BS_ALL = 0xFFFFFFFF,
|
||||||
|
|
||||||
|
@ -356,9 +355,6 @@ public enum CollisionFlags : uint
|
||||||
BS_ACTIVE = CF_STATIC_OBJECT
|
BS_ACTIVE = CF_STATIC_OBJECT
|
||||||
| CF_KINEMATIC_OBJECT
|
| CF_KINEMATIC_OBJECT
|
||||||
| CF_NO_CONTACT_RESPONSE
|
| CF_NO_CONTACT_RESPONSE
|
||||||
// | BS_VOLUME_DETECT_OBJECT
|
|
||||||
// | BS_PHANTOM_OBJECT
|
|
||||||
// | BS_PHYSICAL_OBJECT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Values for collisions groups and masks
|
// Values for collisions groups and masks
|
||||||
|
@ -1042,18 +1038,6 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern int GetNumConstraintRefs2(IntPtr obj);
|
public static extern int GetNumConstraintRefs2(IntPtr obj);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj);
|
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj);
|
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern Vector3 GetPushVelocity2(IntPtr obj);
|
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern Vector3 GetTurnVelocity2(IntPtr obj);
|
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
|
public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
|
||||||
|
|
||||||
|
@ -1113,6 +1097,15 @@ public static extern float GetMargin2(IntPtr shape);
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
|
public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void DumpAllInfo2(IntPtr sim);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
get { return new NullPhysicsScene(); }
|
get { return new NullPhysicsScene(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestAssetDelegate RequestAssetMethod { private get; set; }
|
public RequestAssetDelegate RequestAssetMethod { get; set; }
|
||||||
|
|
||||||
public virtual void TriggerPhysicsBasedRestart()
|
public virtual void TriggerPhysicsBasedRestart()
|
||||||
{
|
{
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private bool m_hackSentFly = false;
|
private bool m_hackSentFly = false;
|
||||||
private int m_requestedUpdateFrequency = 0;
|
private int m_requestedUpdateFrequency = 0;
|
||||||
private Vector3 m_taintPosition;
|
private Vector3 m_taintPosition;
|
||||||
|
internal bool m_avatarplanted = false;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force
|
/// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force
|
||||||
/// while calculatios are going on
|
/// while calculatios are going on
|
||||||
|
@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
m_iscollidingObj = value;
|
m_iscollidingObj = value;
|
||||||
if (value)
|
if (value && !m_avatarplanted)
|
||||||
m_pidControllerActive = false;
|
m_pidControllerActive = false;
|
||||||
else
|
else
|
||||||
m_pidControllerActive = true;
|
m_pidControllerActive = true;
|
||||||
|
|
|
@ -63,6 +63,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
private bool m_isphysical;
|
private bool m_isphysical;
|
||||||
|
|
||||||
|
public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } }
|
||||||
|
private int m_expectedCollisionContacts = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
|
/// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -97,6 +100,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private Vector3 m_taintAngularLock = Vector3.One;
|
private Vector3 m_taintAngularLock = Vector3.One;
|
||||||
private IntPtr Amotor = IntPtr.Zero;
|
private IntPtr Amotor = IntPtr.Zero;
|
||||||
|
|
||||||
|
private object m_assetsLock = new object();
|
||||||
|
private bool m_assetFailed = false;
|
||||||
|
|
||||||
private Vector3 m_PIDTarget;
|
private Vector3 m_PIDTarget;
|
||||||
private float m_PIDTau;
|
private float m_PIDTau;
|
||||||
private float PID_D = 35f;
|
private float PID_D = 35f;
|
||||||
|
@ -279,6 +285,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
m_taintadd = true;
|
m_taintadd = true;
|
||||||
|
m_assetFailed = false;
|
||||||
_parent_scene.AddPhysicsActorTaint(this);
|
_parent_scene.AddPhysicsActorTaint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,8 +341,17 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
prim_geom = geom;
|
prim_geom = geom;
|
||||||
//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
|
//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
|
||||||
|
|
||||||
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
if (m_assetFailed)
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, 0);
|
||||||
|
d.GeomSetCollideBits(prim_geom, BadAssetColideBits());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
||||||
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
_parent_scene.geom_name_map[prim_geom] = Name;
|
_parent_scene.geom_name_map[prim_geom] = Name;
|
||||||
_parent_scene.actor_name_map[prim_geom] = this;
|
_parent_scene.actor_name_map[prim_geom] = this;
|
||||||
|
@ -398,8 +414,17 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
myrot.W = _orientation.W;
|
myrot.W = _orientation.W;
|
||||||
d.BodySetQuaternion(Body, ref myrot);
|
d.BodySetQuaternion(Body, ref myrot);
|
||||||
d.GeomSetBody(prim_geom, Body);
|
d.GeomSetBody(prim_geom, Body);
|
||||||
m_collisionCategories |= CollisionCategories.Body;
|
|
||||||
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
|
if (m_assetFailed)
|
||||||
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, 0);
|
||||||
|
d.GeomSetCollideBits(prim_geom, BadAssetColideBits());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_collisionCategories |= CollisionCategories.Body;
|
||||||
|
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
|
||||||
|
}
|
||||||
|
|
||||||
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
@ -771,8 +796,16 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_collisionCategories &= ~CollisionCategories.Body;
|
m_collisionCategories &= ~CollisionCategories.Body;
|
||||||
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
|
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
|
||||||
|
|
||||||
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
if (m_assetFailed)
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, 0);
|
||||||
|
d.GeomSetCollideBits(prim_geom, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
||||||
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
d.BodyDestroy(Body);
|
d.BodyDestroy(Body);
|
||||||
lock (childrenPrim)
|
lock (childrenPrim)
|
||||||
|
@ -796,8 +829,17 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_collisionCategories &= ~CollisionCategories.Body;
|
m_collisionCategories &= ~CollisionCategories.Body;
|
||||||
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
|
m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
|
||||||
|
|
||||||
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
if (m_assetFailed)
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, 0);
|
||||||
|
d.GeomSetCollideBits(prim_geom, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
||||||
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
Body = IntPtr.Zero;
|
Body = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
@ -809,6 +851,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
|
private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
|
||||||
|
|
||||||
|
public int BadAssetColideBits()
|
||||||
|
{
|
||||||
|
return (m_isphysical ? (int)CollisionCategories.Land : 0);
|
||||||
|
}
|
||||||
|
|
||||||
private void setMesh(OdeScene parent_scene, IMesh mesh)
|
private void setMesh(OdeScene parent_scene, IMesh mesh)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh);
|
// m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh);
|
||||||
|
@ -840,7 +887,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
int vertexStride, triStride;
|
int vertexStride, triStride;
|
||||||
mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
|
mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
|
||||||
mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
|
mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
|
||||||
|
m_expectedCollisionContacts = indexCount;
|
||||||
mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
|
mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
|
||||||
|
|
||||||
// We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at
|
// We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at
|
||||||
|
@ -1087,8 +1134,16 @@ Console.WriteLine("ZProcessTaints for " + Name);
|
||||||
prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
|
prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
|
||||||
|
|
||||||
//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name);
|
//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name);
|
||||||
d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
|
if (prm.m_assetFailed)
|
||||||
d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
|
{
|
||||||
|
d.GeomSetCategoryBits(prm.prim_geom, 0);
|
||||||
|
d.GeomSetCollideBits(prm.prim_geom, prm.BadAssetColideBits());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
|
||||||
|
d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
d.Quaternion quat = new d.Quaternion();
|
d.Quaternion quat = new d.Quaternion();
|
||||||
quat.W = prm._orientation.W;
|
quat.W = prm._orientation.W;
|
||||||
|
@ -1133,10 +1188,18 @@ Console.WriteLine("ZProcessTaints for " + Name);
|
||||||
m_collisionCategories |= CollisionCategories.Body;
|
m_collisionCategories |= CollisionCategories.Body;
|
||||||
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
|
m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
|
||||||
|
|
||||||
//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name);
|
if (m_assetFailed)
|
||||||
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
{
|
||||||
//Console.WriteLine(" Post GeomSetCategoryBits 2");
|
d.GeomSetCategoryBits(prim_geom, 0);
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
d.GeomSetCollideBits(prim_geom, BadAssetColideBits());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name);
|
||||||
|
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
||||||
|
//Console.WriteLine(" Post GeomSetCategoryBits 2");
|
||||||
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
d.Quaternion quat2 = new d.Quaternion();
|
d.Quaternion quat2 = new d.Quaternion();
|
||||||
quat2.W = _orientation.W;
|
quat2.W = _orientation.W;
|
||||||
|
@ -1297,8 +1360,16 @@ Console.WriteLine("ZProcessTaints for " + Name);
|
||||||
disableBodySoft();
|
disableBodySoft();
|
||||||
}
|
}
|
||||||
|
|
||||||
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
if (m_assetFailed)
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, 0);
|
||||||
|
d.GeomSetCollideBits(prim_geom, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
||||||
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
if (IsPhysical)
|
if (IsPhysical)
|
||||||
{
|
{
|
||||||
|
@ -1319,8 +1390,16 @@ Console.WriteLine("ZProcessTaints for " + Name);
|
||||||
if (m_collidesWater)
|
if (m_collidesWater)
|
||||||
m_collisionFlags |= CollisionCategories.Water;
|
m_collisionFlags |= CollisionCategories.Water;
|
||||||
|
|
||||||
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
if (m_assetFailed)
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, 0);
|
||||||
|
d.GeomSetCollideBits(prim_geom, BadAssetColideBits());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
|
||||||
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
}
|
||||||
|
|
||||||
if (IsPhysical)
|
if (IsPhysical)
|
||||||
{
|
{
|
||||||
|
@ -1377,6 +1456,7 @@ Console.WriteLine("CreateGeom:");
|
||||||
{
|
{
|
||||||
//Console.WriteLine(" CreateGeom 1");
|
//Console.WriteLine(" CreateGeom 1");
|
||||||
SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
|
SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
|
||||||
|
m_expectedCollisionContacts = 3;
|
||||||
}
|
}
|
||||||
catch (AccessViolationException)
|
catch (AccessViolationException)
|
||||||
{
|
{
|
||||||
|
@ -1391,6 +1471,7 @@ Console.WriteLine("CreateGeom:");
|
||||||
{
|
{
|
||||||
//Console.WriteLine(" CreateGeom 2");
|
//Console.WriteLine(" CreateGeom 2");
|
||||||
SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
|
SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
|
||||||
|
m_expectedCollisionContacts = 4;
|
||||||
}
|
}
|
||||||
catch (AccessViolationException)
|
catch (AccessViolationException)
|
||||||
{
|
{
|
||||||
|
@ -1406,6 +1487,7 @@ Console.WriteLine("CreateGeom:");
|
||||||
{
|
{
|
||||||
//Console.WriteLine(" CreateGeom 3");
|
//Console.WriteLine(" CreateGeom 3");
|
||||||
SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
|
SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
|
||||||
|
m_expectedCollisionContacts = 4;
|
||||||
}
|
}
|
||||||
catch (AccessViolationException)
|
catch (AccessViolationException)
|
||||||
{
|
{
|
||||||
|
@ -1421,6 +1503,7 @@ Console.WriteLine("CreateGeom:");
|
||||||
{
|
{
|
||||||
//Console.WriteLine(" CreateGeom 4");
|
//Console.WriteLine(" CreateGeom 4");
|
||||||
SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
|
SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
|
||||||
|
m_expectedCollisionContacts = 4;
|
||||||
}
|
}
|
||||||
catch (AccessViolationException)
|
catch (AccessViolationException)
|
||||||
{
|
{
|
||||||
|
@ -1446,11 +1529,13 @@ Console.WriteLine("CreateGeom:");
|
||||||
_parent_scene.geom_name_map.Remove(prim_geom);
|
_parent_scene.geom_name_map.Remove(prim_geom);
|
||||||
_parent_scene.actor_name_map.Remove(prim_geom);
|
_parent_scene.actor_name_map.Remove(prim_geom);
|
||||||
d.GeomDestroy(prim_geom);
|
d.GeomDestroy(prim_geom);
|
||||||
|
m_expectedCollisionContacts = 0;
|
||||||
prim_geom = IntPtr.Zero;
|
prim_geom = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
catch (System.AccessViolationException)
|
catch (System.AccessViolationException)
|
||||||
{
|
{
|
||||||
prim_geom = IntPtr.Zero;
|
prim_geom = IntPtr.Zero;
|
||||||
|
m_expectedCollisionContacts = 0;
|
||||||
m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
|
m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1489,6 +1574,10 @@ Console.WriteLine("CreateGeom:");
|
||||||
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
|
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
|
||||||
// createmesh returns null when it's a shape that isn't a cube.
|
// createmesh returns null when it's a shape that isn't a cube.
|
||||||
// m_log.Debug(m_localID);
|
// m_log.Debug(m_localID);
|
||||||
|
if (mesh == null)
|
||||||
|
CheckMeshAsset();
|
||||||
|
else
|
||||||
|
m_assetFailed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SPAM
|
#if SPAM
|
||||||
|
@ -1988,7 +2077,14 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
// Don't need to re-enable body.. it's done in SetMesh
|
// Don't need to re-enable body.. it's done in SetMesh
|
||||||
|
|
||||||
if (_parent_scene.needsMeshing(_pbs))
|
if (_parent_scene.needsMeshing(_pbs))
|
||||||
|
{
|
||||||
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
||||||
|
if (mesh == null)
|
||||||
|
CheckMeshAsset();
|
||||||
|
else
|
||||||
|
m_assetFailed = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateGeom(m_targetSpace, mesh);
|
CreateGeom(m_targetSpace, mesh);
|
||||||
|
@ -2040,14 +2136,19 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
m_collisionFlags &= ~CollisionCategories.Water;
|
m_collisionFlags &= ~CollisionCategories.Water;
|
||||||
}
|
}
|
||||||
|
|
||||||
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
if (m_assetFailed)
|
||||||
}
|
d.GeomSetCollideBits(prim_geom, BadAssetColideBits());
|
||||||
|
else
|
||||||
|
|
||||||
|
d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change prim in response to a shape taint.
|
/// Change prim in response to a shape taint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void changeshape()
|
private void changeshape()
|
||||||
{
|
{
|
||||||
|
m_taintshape = false;
|
||||||
|
|
||||||
// Cleanup of old prim geometry and Bodies
|
// Cleanup of old prim geometry and Bodies
|
||||||
if (IsPhysical && Body != IntPtr.Zero)
|
if (IsPhysical && Body != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
|
@ -2075,6 +2176,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
|
|
||||||
IMesh mesh = null;
|
IMesh mesh = null;
|
||||||
|
|
||||||
|
|
||||||
if (_parent_scene.needsMeshing(_pbs))
|
if (_parent_scene.needsMeshing(_pbs))
|
||||||
{
|
{
|
||||||
// Don't need to re-enable body.. it's done in CreateMesh
|
// Don't need to re-enable body.. it's done in CreateMesh
|
||||||
|
@ -2085,6 +2187,10 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
|
|
||||||
// createmesh returns null when it doesn't mesh.
|
// createmesh returns null when it doesn't mesh.
|
||||||
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
||||||
|
if (mesh == null)
|
||||||
|
CheckMeshAsset();
|
||||||
|
else
|
||||||
|
m_assetFailed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateGeom(m_targetSpace, mesh);
|
CreateGeom(m_targetSpace, mesh);
|
||||||
|
@ -2121,7 +2227,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
}
|
}
|
||||||
|
|
||||||
resetCollisionAccounting();
|
resetCollisionAccounting();
|
||||||
m_taintshape = false;
|
// m_taintshape = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2387,6 +2493,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_pbs = value;
|
_pbs = value;
|
||||||
|
m_assetFailed = false;
|
||||||
m_taintshape = true;
|
m_taintshape = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2395,15 +2502,15 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// Averate previous velocity with the new one so
|
// Average previous velocity with the new one so
|
||||||
// client object interpolation works a 'little' better
|
// client object interpolation works a 'little' better
|
||||||
if (_zeroFlag)
|
if (_zeroFlag)
|
||||||
return Vector3.Zero;
|
return Vector3.Zero;
|
||||||
|
|
||||||
Vector3 returnVelocity = Vector3.Zero;
|
Vector3 returnVelocity = Vector3.Zero;
|
||||||
returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
|
returnVelocity.X = (m_lastVelocity.X + _velocity.X) * 0.5f; // 0.5f is mathematically equiv to '/ 2'
|
||||||
returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
|
returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) * 0.5f;
|
||||||
returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
|
returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) * 0.5f;
|
||||||
return returnVelocity;
|
return returnVelocity;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
|
@ -2600,6 +2707,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
Vector3 pv = Vector3.Zero;
|
Vector3 pv = Vector3.Zero;
|
||||||
bool lastZeroFlag = _zeroFlag;
|
bool lastZeroFlag = _zeroFlag;
|
||||||
|
float m_minvelocity = 0;
|
||||||
if (Body != (IntPtr)0) // FIXME -> or if it is a joint
|
if (Body != (IntPtr)0) // FIXME -> or if it is a joint
|
||||||
{
|
{
|
||||||
d.Vector3 vec = d.BodyGetPosition(Body);
|
d.Vector3 vec = d.BodyGetPosition(Body);
|
||||||
|
@ -2753,7 +2861,20 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
_acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f);
|
_acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f);
|
||||||
//m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
|
//m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
|
||||||
|
|
||||||
if (_velocity.ApproxEquals(pv, 0.5f))
|
// Note here that linearvelocity is affecting angular velocity... so I'm guessing this is a vehicle specific thing...
|
||||||
|
// it does make sense to do this for tiny little instabilities with physical prim, however 0.5m/frame is fairly large.
|
||||||
|
// reducing this to 0.02m/frame seems to help the angular rubberbanding quite a bit, however, to make sure it doesn't affect elevators and vehicles
|
||||||
|
// adding these logical exclusion situations to maintain this where I think it was intended to be.
|
||||||
|
if (m_throttleUpdates || m_usePID || (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) || (Amotor != IntPtr.Zero))
|
||||||
|
{
|
||||||
|
m_minvelocity = 0.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_minvelocity = 0.02f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_velocity.ApproxEquals(pv, m_minvelocity))
|
||||||
{
|
{
|
||||||
m_rotationalVelocity = pv;
|
m_rotationalVelocity = pv;
|
||||||
}
|
}
|
||||||
|
@ -3211,5 +3332,37 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
m_material = pMaterial;
|
m_material = pMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CheckMeshAsset()
|
||||||
|
{
|
||||||
|
if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
|
||||||
|
{
|
||||||
|
m_assetFailed = true;
|
||||||
|
Util.FireAndForget(delegate
|
||||||
|
{
|
||||||
|
RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
|
||||||
|
if (assetProvider != null)
|
||||||
|
assetProvider(_pbs.SculptTexture, MeshAssetReveived);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshAssetReveived(AssetBase asset)
|
||||||
|
{
|
||||||
|
if (asset.Data != null && asset.Data.Length > 0)
|
||||||
|
{
|
||||||
|
if (!_pbs.SculptEntry)
|
||||||
|
return;
|
||||||
|
if (_pbs.SculptTexture.ToString() != asset.ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_pbs.SculptData = new byte[asset.Data.Length];
|
||||||
|
asset.Data.CopyTo(_pbs.SculptData, 0);
|
||||||
|
// m_assetFailed = false;
|
||||||
|
m_taintshape = true;
|
||||||
|
_parent_scene.AddPhysicsActorTaint(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -336,6 +336,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
public int geomContactPointsStartthrottle = 3;
|
public int geomContactPointsStartthrottle = 3;
|
||||||
public int geomUpdatesPerThrottledUpdate = 15;
|
public int geomUpdatesPerThrottledUpdate = 15;
|
||||||
|
private const int avatarExpectedContacts = 3;
|
||||||
|
|
||||||
public float bodyPIDD = 35f;
|
public float bodyPIDD = 35f;
|
||||||
public float bodyPIDG = 25;
|
public float bodyPIDG = 25;
|
||||||
|
@ -474,6 +475,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private OdePrim cp1;
|
private OdePrim cp1;
|
||||||
private OdeCharacter cc2;
|
private OdeCharacter cc2;
|
||||||
private OdePrim cp2;
|
private OdePrim cp2;
|
||||||
|
private int p1ExpectedPoints = 0;
|
||||||
|
private int p2ExpectedPoints = 0;
|
||||||
//private int cStartStop = 0;
|
//private int cStartStop = 0;
|
||||||
//private string cDictKey = "";
|
//private string cDictKey = "";
|
||||||
|
|
||||||
|
@ -498,6 +501,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public int physics_logging_interval = 0;
|
public int physics_logging_interval = 0;
|
||||||
public bool physics_logging_append_existing_logfile = false;
|
public bool physics_logging_append_existing_logfile = false;
|
||||||
|
|
||||||
|
private bool avplanted = false;
|
||||||
|
private bool av_av_collisions_off = false;
|
||||||
|
|
||||||
public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
|
public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
|
||||||
public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
|
public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
|
||||||
|
|
||||||
|
@ -640,11 +646,14 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
|
avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
|
||||||
avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
|
avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
|
||||||
avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
|
avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
|
||||||
|
avplanted = physicsconfig.GetBoolean("av_planted", false);
|
||||||
|
av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false);
|
||||||
|
|
||||||
IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
|
IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
|
||||||
|
|
||||||
contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
|
contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
|
||||||
|
|
||||||
geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3);
|
geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5);
|
||||||
geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
|
geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
|
||||||
geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
|
geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
|
||||||
|
|
||||||
|
@ -660,6 +669,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
|
MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
|
||||||
m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
|
m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
||||||
{
|
{
|
||||||
avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f);
|
avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f);
|
||||||
|
@ -1065,6 +1076,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
PhysicsActor p1;
|
PhysicsActor p1;
|
||||||
PhysicsActor p2;
|
PhysicsActor p2;
|
||||||
|
|
||||||
|
p1ExpectedPoints = 0;
|
||||||
|
p2ExpectedPoints = 0;
|
||||||
|
|
||||||
if (!actor_name_map.TryGetValue(g1, out p1))
|
if (!actor_name_map.TryGetValue(g1, out p1))
|
||||||
{
|
{
|
||||||
p1 = PANull;
|
p1 = PANull;
|
||||||
|
@ -1121,9 +1135,13 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
switch (p1.PhysicsActorType)
|
switch (p1.PhysicsActorType)
|
||||||
{
|
{
|
||||||
case (int)ActorTypes.Agent:
|
case (int)ActorTypes.Agent:
|
||||||
|
p1ExpectedPoints = avatarExpectedContacts;
|
||||||
p2.CollidingObj = true;
|
p2.CollidingObj = true;
|
||||||
break;
|
break;
|
||||||
case (int)ActorTypes.Prim:
|
case (int)ActorTypes.Prim:
|
||||||
|
if (p1 != null && p1 is OdePrim)
|
||||||
|
p1ExpectedPoints = ((OdePrim) p1).ExpectedCollisionContacts;
|
||||||
|
|
||||||
if (p2.Velocity.LengthSquared() > 0.0f)
|
if (p2.Velocity.LengthSquared() > 0.0f)
|
||||||
p2.CollidingObj = true;
|
p2.CollidingObj = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1298,6 +1316,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
|
if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
|
||||||
skipThisContact = true; // No collision on volume detect prims
|
skipThisContact = true; // No collision on volume detect prims
|
||||||
|
|
||||||
|
if (av_av_collisions_off)
|
||||||
|
if ((p1 is OdeCharacter) && (p2 is OdeCharacter))
|
||||||
|
skipThisContact = true;
|
||||||
|
|
||||||
if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
|
if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
|
||||||
skipThisContact = true; // No collision on volume detect prims
|
skipThisContact = true; // No collision on volume detect prims
|
||||||
|
|
||||||
|
@ -1319,6 +1341,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
|
if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
|
||||||
(Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
|
(Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
|
||||||
{
|
{
|
||||||
|
p2ExpectedPoints = avatarExpectedContacts;
|
||||||
// Avatar is moving on terrain, use the movement terrain contact
|
// Avatar is moving on terrain, use the movement terrain contact
|
||||||
AvatarMovementTerrainContact.geom = curContact;
|
AvatarMovementTerrainContact.geom = curContact;
|
||||||
|
|
||||||
|
@ -1332,6 +1355,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
if (p2.PhysicsActorType == (int)ActorTypes.Agent)
|
if (p2.PhysicsActorType == (int)ActorTypes.Agent)
|
||||||
{
|
{
|
||||||
|
p2ExpectedPoints = avatarExpectedContacts;
|
||||||
// Avatar is standing on terrain, use the non moving terrain contact
|
// Avatar is standing on terrain, use the non moving terrain contact
|
||||||
TerrainContact.geom = curContact;
|
TerrainContact.geom = curContact;
|
||||||
|
|
||||||
|
@ -1356,9 +1380,18 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p2 is OdePrim)
|
if (p2 is OdePrim)
|
||||||
material = ((OdePrim)p2).m_material;
|
{
|
||||||
|
material = ((OdePrim) p2).m_material;
|
||||||
|
p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unnessesary because p1 is defined above
|
||||||
|
//if (p1 is OdePrim)
|
||||||
|
// {
|
||||||
|
// p1ExpectedPoints = ((OdePrim)p1).ExpectedCollisionContacts;
|
||||||
|
// }
|
||||||
//m_log.DebugFormat("Material: {0}", material);
|
//m_log.DebugFormat("Material: {0}", material);
|
||||||
|
|
||||||
m_materialContacts[material, movintYN].geom = curContact;
|
m_materialContacts[material, movintYN].geom = curContact;
|
||||||
|
|
||||||
if (m_global_contactcount < maxContactsbeforedeath)
|
if (m_global_contactcount < maxContactsbeforedeath)
|
||||||
|
@ -1379,7 +1412,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
int material = (int)Material.Wood;
|
int material = (int)Material.Wood;
|
||||||
|
|
||||||
if (p2 is OdePrim)
|
if (p2 is OdePrim)
|
||||||
|
{
|
||||||
material = ((OdePrim)p2).m_material;
|
material = ((OdePrim)p2).m_material;
|
||||||
|
p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts;
|
||||||
|
}
|
||||||
|
|
||||||
//m_log.DebugFormat("Material: {0}", material);
|
//m_log.DebugFormat("Material: {0}", material);
|
||||||
m_materialContacts[material, movintYN].geom = curContact;
|
m_materialContacts[material, movintYN].geom = curContact;
|
||||||
|
@ -1429,6 +1465,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
|
if ((p2.PhysicsActorType == (int)ActorTypes.Agent))
|
||||||
{
|
{
|
||||||
|
p2ExpectedPoints = avatarExpectedContacts;
|
||||||
if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
|
if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
|
||||||
{
|
{
|
||||||
// Avatar is moving on a prim, use the Movement prim contact
|
// Avatar is moving on a prim, use the Movement prim contact
|
||||||
|
@ -1458,7 +1495,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
int material = (int)Material.Wood;
|
int material = (int)Material.Wood;
|
||||||
|
|
||||||
if (p2 is OdePrim)
|
if (p2 is OdePrim)
|
||||||
|
{
|
||||||
material = ((OdePrim)p2).m_material;
|
material = ((OdePrim)p2).m_material;
|
||||||
|
p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts;
|
||||||
|
}
|
||||||
|
|
||||||
//m_log.DebugFormat("Material: {0}", material);
|
//m_log.DebugFormat("Material: {0}", material);
|
||||||
m_materialContacts[material, 0].geom = curContact;
|
m_materialContacts[material, 0].geom = curContact;
|
||||||
|
@ -1480,7 +1520,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
collision_accounting_events(p1, p2, maxDepthContact);
|
collision_accounting_events(p1, p2, maxDepthContact);
|
||||||
|
|
||||||
if (count > geomContactPointsStartthrottle)
|
if (count > ((p1ExpectedPoints + p2ExpectedPoints) * 0.25) + (geomContactPointsStartthrottle))
|
||||||
{
|
{
|
||||||
// If there are more then 3 contact points, it's likely
|
// If there are more then 3 contact points, it's likely
|
||||||
// that we've got a pile of objects, so ...
|
// that we've got a pile of objects, so ...
|
||||||
|
@ -1943,6 +1983,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
newAv.Flying = isFlying;
|
newAv.Flying = isFlying;
|
||||||
newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
|
newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
|
||||||
|
newAv.m_avatarplanted = avplanted;
|
||||||
|
|
||||||
return newAv;
|
return newAv;
|
||||||
}
|
}
|
||||||
|
@ -1958,6 +1999,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
internal void AddCharacter(OdeCharacter chr)
|
internal void AddCharacter(OdeCharacter chr)
|
||||||
{
|
{
|
||||||
|
chr.m_avatarplanted = avplanted;
|
||||||
if (!_characters.Contains(chr))
|
if (!_characters.Contains(chr))
|
||||||
{
|
{
|
||||||
_characters.Add(chr);
|
_characters.Add(chr);
|
||||||
|
|
|
@ -56,6 +56,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||||
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||||
using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
|
using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
|
||||||
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
||||||
|
using RegionFlags = OpenSim.Framework.RegionFlags;
|
||||||
|
|
||||||
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
|
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
|
||||||
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
|
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
|
||||||
|
@ -3772,6 +3773,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Returns the name of the child prim or seated avatar matching the
|
||||||
|
/// specified link number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="linknum">
|
||||||
|
/// The number of a link in the linkset or a link-related constant.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// The name determined to match the specified link number.
|
||||||
|
/// </returns>
|
||||||
|
/// <remarks>
|
||||||
/// The rules governing the returned name are not simple. The only
|
/// The rules governing the returned name are not simple. The only
|
||||||
/// time a blank name is returned is if the target prim has a blank
|
/// time a blank name is returned is if the target prim has a blank
|
||||||
/// name. If no prim with the given link number can be found then
|
/// name. If no prim with the given link number can be found then
|
||||||
|
@ -3799,10 +3810,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
/// Mentions NULL_KEY being returned
|
/// Mentions NULL_KEY being returned
|
||||||
/// http://wiki.secondlife.com/wiki/LlGetLinkName
|
/// http://wiki.secondlife.com/wiki/LlGetLinkName
|
||||||
/// Mentions using the LINK_* constants, some of which are negative
|
/// Mentions using the LINK_* constants, some of which are negative
|
||||||
/// </summary>
|
/// </remarks>
|
||||||
public LSL_String llGetLinkName(int linknum)
|
public LSL_String llGetLinkName(int linknum)
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
|
// simplest case, this prims link number
|
||||||
|
if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS)
|
||||||
|
return m_host.Name;
|
||||||
|
|
||||||
// parse for sitting avatare-names
|
// parse for sitting avatare-names
|
||||||
List<String> nametable = new List<String>();
|
List<String> nametable = new List<String>();
|
||||||
World.ForEachRootScenePresence(delegate(ScenePresence presence)
|
World.ForEachRootScenePresence(delegate(ScenePresence presence)
|
||||||
|
@ -3826,10 +3841,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
return nametable[totalprims - linknum];
|
return nametable[totalprims - linknum];
|
||||||
}
|
}
|
||||||
|
|
||||||
// simplest case, this prims link number
|
|
||||||
if (m_host.LinkNum == linknum)
|
|
||||||
return m_host.Name;
|
|
||||||
|
|
||||||
// Single prim
|
// Single prim
|
||||||
if (m_host.LinkNum == 0)
|
if (m_host.LinkNum == 0)
|
||||||
{
|
{
|
||||||
|
@ -3978,7 +3989,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
World.RegionInfo.RegionName+" "+
|
World.RegionInfo.RegionName+" "+
|
||||||
m_host.AbsolutePosition.ToString(),
|
m_host.AbsolutePosition.ToString(),
|
||||||
agentItem.ID, true, m_host.AbsolutePosition,
|
agentItem.ID, true, m_host.AbsolutePosition,
|
||||||
bucket);
|
bucket, true); // TODO: May actually send no timestamp
|
||||||
|
|
||||||
m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
|
m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
|
||||||
}
|
}
|
||||||
|
@ -4006,7 +4017,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
|
Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
|
||||||
m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
|
if (text.Length > 254)
|
||||||
|
text = text.Remove(254);
|
||||||
|
|
||||||
|
byte[] data;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
data = Util.UTF8.GetBytes(text);
|
||||||
|
if (data.Length > 254)
|
||||||
|
text = text.Substring(0, text.Length - 1);
|
||||||
|
} while (data.Length > 254);
|
||||||
|
|
||||||
|
m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
|
||||||
//m_host.ParentGroup.HasGroupChanged = true;
|
//m_host.ParentGroup.HasGroupChanged = true;
|
||||||
//m_host.ParentGroup.ScheduleGroupForFullUpdate();
|
//m_host.ParentGroup.ScheduleGroupForFullUpdate();
|
||||||
}
|
}
|
||||||
|
@ -6442,15 +6464,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
byte[] bucket = new byte[] { (byte)AssetType.Folder };
|
byte[] bucket = new byte[] { (byte)AssetType.Folder };
|
||||||
|
|
||||||
|
Vector3 pos = m_host.AbsolutePosition;
|
||||||
|
|
||||||
GridInstantMessage msg = new GridInstantMessage(World,
|
GridInstantMessage msg = new GridInstantMessage(World,
|
||||||
m_host.UUID, m_host.Name + ", an object owned by " +
|
m_host.OwnerID, m_host.Name, destID,
|
||||||
resolveName(m_host.OwnerID) + ",", destID,
|
|
||||||
(byte)InstantMessageDialog.TaskInventoryOffered,
|
(byte)InstantMessageDialog.TaskInventoryOffered,
|
||||||
false, category + "\n" + m_host.Name + " is located at " +
|
false, string.Format("'{0}'", category),
|
||||||
World.RegionInfo.RegionName + " " +
|
// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06
|
||||||
m_host.AbsolutePosition.ToString(),
|
// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
|
||||||
folderID, true, m_host.AbsolutePosition,
|
folderID, false, pos,
|
||||||
bucket);
|
bucket, false);
|
||||||
|
|
||||||
m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
|
m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
|
||||||
}
|
}
|
||||||
|
@ -9301,11 +9324,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
|
|
||||||
GridRegion info;
|
GridRegion info;
|
||||||
|
|
||||||
if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator?
|
if (World.RegionInfo.RegionName == simulator)
|
||||||
|
info = new GridRegion(World.RegionInfo);
|
||||||
info = new GridRegion(m_ScriptEngine.World.RegionInfo);
|
|
||||||
else
|
else
|
||||||
info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
|
info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
|
||||||
|
|
||||||
switch (data)
|
switch (data)
|
||||||
{
|
{
|
||||||
|
@ -9315,9 +9337,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
ScriptSleep(1000);
|
ScriptSleep(1000);
|
||||||
return UUID.Zero.ToString();
|
return UUID.Zero.ToString();
|
||||||
}
|
}
|
||||||
if (m_ScriptEngine.World.RegionInfo.RegionName != simulator)
|
|
||||||
|
bool isHypergridRegion = false;
|
||||||
|
|
||||||
|
if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "")
|
||||||
|
{
|
||||||
|
// Hypergrid is currently placing real destination region co-ords into RegionSecret.
|
||||||
|
// But other code can also use this field for a genuine RegionSecret! Therefore, if
|
||||||
|
// anything is present we need to disambiguate.
|
||||||
|
//
|
||||||
|
// FIXME: Hypergrid should be storing this data in a different field.
|
||||||
|
RegionFlags regionFlags
|
||||||
|
= (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(
|
||||||
|
info.ScopeID, info.RegionID);
|
||||||
|
isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHypergridRegion)
|
||||||
{
|
{
|
||||||
//Hypergrid Region co-ordinates
|
|
||||||
uint rx = 0, ry = 0;
|
uint rx = 0, ry = 0;
|
||||||
Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
|
Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
|
||||||
|
|
||||||
|
@ -9328,7 +9365,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Local-cooridnates
|
// Local grid co-oridnates
|
||||||
reply = new LSL_Vector(
|
reply = new LSL_Vector(
|
||||||
info.RegionLocX,
|
info.RegionLocX,
|
||||||
info.RegionLocY,
|
info.RegionLocY,
|
||||||
|
|
|
@ -3545,10 +3545,96 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void osSetContentType(LSL_Key id, string type)
|
public void osSetContentType(LSL_Key id, string type)
|
||||||
{
|
{
|
||||||
CheckThreatLevel(ThreatLevel.High,"osSetResponseType");
|
CheckThreatLevel(ThreatLevel.High, "osSetContentType");
|
||||||
|
|
||||||
if (m_UrlModule != null)
|
if (m_UrlModule != null)
|
||||||
m_UrlModule.HttpContentType(new UUID(id),type);
|
m_UrlModule.HttpContentType(new UUID(id),type);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/// Shout an error if the object owner did not grant the script the specified permissions.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="perms"></param>
|
||||||
|
/// <returns>boolean indicating whether an error was shouted.</returns>
|
||||||
|
protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix)
|
||||||
|
{
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
bool fail = false;
|
||||||
|
if (m_item.PermsGranter != m_host.OwnerID)
|
||||||
|
{
|
||||||
|
fail = true;
|
||||||
|
OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix));
|
||||||
|
}
|
||||||
|
else if ((m_item.PermsMask & perms) == 0)
|
||||||
|
{
|
||||||
|
fail = true;
|
||||||
|
OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DropAttachment(bool checkPerms)
|
||||||
|
{
|
||||||
|
if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
|
||||||
|
ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
|
||||||
|
|
||||||
|
if (attachmentsModule != null && sp != null)
|
||||||
|
{
|
||||||
|
attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot)
|
||||||
|
{
|
||||||
|
if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
|
||||||
|
ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
|
||||||
|
|
||||||
|
if (attachmentsModule != null && sp != null)
|
||||||
|
{
|
||||||
|
attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osDropAttachment()
|
||||||
|
{
|
||||||
|
CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment");
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
|
DropAttachment(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osForceDropAttachment()
|
||||||
|
{
|
||||||
|
CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment");
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
|
DropAttachment(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
|
||||||
|
{
|
||||||
|
CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt");
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
|
DropAttachmentAt(true, pos, rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
|
||||||
|
{
|
||||||
|
CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt");
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
|
DropAttachmentAt(false, pos, rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -394,5 +394,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
void osSetContentType(LSL_Key id, string type);
|
void osSetContentType(LSL_Key id, string type);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to drop an attachment to the ground
|
||||||
|
/// </summary>
|
||||||
|
void osDropAttachment();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to drop an attachment to the ground while bypassing the script permissions
|
||||||
|
/// </summary>
|
||||||
|
void osForceDropAttachment();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to drop an attachment at the specified coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos"></param>
|
||||||
|
/// <param name="rot"></param>
|
||||||
|
void osDropAttachmentAt(vector pos, rotation rot);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos"></param>
|
||||||
|
/// <param name="rot"></param>
|
||||||
|
void osForceDropAttachmentAt(vector pos, rotation rot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -972,5 +972,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
{
|
{
|
||||||
m_OSSL_Functions.osSetContentType(id,type);
|
m_OSSL_Functions.osSetContentType(id,type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void osDropAttachment()
|
||||||
|
{
|
||||||
|
m_OSSL_Functions.osDropAttachment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osForceDropAttachment()
|
||||||
|
{
|
||||||
|
m_OSSL_Functions.osForceDropAttachment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osDropAttachmentAt(vector pos, rotation rot)
|
||||||
|
{
|
||||||
|
m_OSSL_Functions.osDropAttachmentAt(pos, rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osForceDropAttachmentAt(vector pos, rotation rot)
|
||||||
|
{
|
||||||
|
m_OSSL_Functions.osForceDropAttachmentAt(pos, rot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,9 +96,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
if (part == null)
|
if (part == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ((part.ScriptEvents & scriptEvents.money) == 0)
|
||||||
|
part = part.ParentGroup.RootPart;
|
||||||
|
|
||||||
m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount);
|
m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount);
|
||||||
|
|
||||||
part = part.ParentGroup.RootPart;
|
// part = part.ParentGroup.RootPart;
|
||||||
money(part.LocalId, agentID, amount);
|
money(part.LocalId, agentID, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// User statistics sessions keyed by agent ID
|
/// User statistics sessions keyed by agent ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>();
|
private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>();
|
||||||
|
|
||||||
private List<Scene> m_scenes = new List<Scene>();
|
private List<Scene> m_scenes = new List<Scene>();
|
||||||
private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
|
private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
|
||||||
|
@ -319,14 +319,18 @@ namespace OpenSim.Region.UserStatistics
|
||||||
|
|
||||||
private void OnMakeRootAgent(ScenePresence agent)
|
private void OnMakeRootAgent(ScenePresence agent)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}",
|
||||||
|
// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name);
|
||||||
|
|
||||||
lock (m_sessions)
|
lock (m_sessions)
|
||||||
{
|
{
|
||||||
UserSessionID uid;
|
UserSession uid;
|
||||||
|
|
||||||
if (!m_sessions.ContainsKey(agent.UUID))
|
if (!m_sessions.ContainsKey(agent.UUID))
|
||||||
{
|
{
|
||||||
UserSessionData usd = UserSessionUtil.newUserSessionData();
|
UserSessionData usd = UserSessionUtil.newUserSessionData();
|
||||||
uid = new UserSessionID();
|
uid = new UserSession();
|
||||||
uid.name_f = agent.Firstname;
|
uid.name_f = agent.Firstname;
|
||||||
uid.name_l = agent.Lastname;
|
uid.name_l = agent.Lastname;
|
||||||
uid.session_data = usd;
|
uid.session_data = usd;
|
||||||
|
@ -411,9 +415,9 @@ namespace OpenSim.Region.UserStatistics
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserSessionID ParseViewerStats(string request, UUID agentID)
|
private UserSession ParseViewerStats(string request, UUID agentID)
|
||||||
{
|
{
|
||||||
UserSessionID uid = new UserSessionID();
|
UserSession uid = new UserSession();
|
||||||
UserSessionData usd;
|
UserSessionData usd;
|
||||||
OSD message = OSDParser.DeserializeLLSDXml(request);
|
OSD message = OSDParser.DeserializeLLSDXml(request);
|
||||||
OSDMap mmap;
|
OSDMap mmap;
|
||||||
|
@ -425,22 +429,25 @@ namespace OpenSim.Region.UserStatistics
|
||||||
if (!m_sessions.ContainsKey(agentID))
|
if (!m_sessions.ContainsKey(agentID))
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID);
|
m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID);
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
uid = m_sessions[agentID];
|
uid = m_sessions[agentID];
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// parse through the beginning to locate the session
|
// parse through the beginning to locate the session
|
||||||
if (message.Type != OSDType.Map)
|
if (message.Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
|
|
||||||
mmap = (OSDMap)message;
|
mmap = (OSDMap)message;
|
||||||
{
|
{
|
||||||
UUID sessionID = mmap["session_id"].AsUUID();
|
UUID sessionID = mmap["session_id"].AsUUID();
|
||||||
|
|
||||||
if (sessionID == UUID.Zero)
|
if (sessionID == UUID.Zero)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
|
|
||||||
|
|
||||||
// search through each session looking for the owner
|
// search through each session looking for the owner
|
||||||
|
@ -459,7 +466,7 @@ namespace OpenSim.Region.UserStatistics
|
||||||
// can't find a session
|
// can't find a session
|
||||||
if (agentID == UUID.Zero)
|
if (agentID == UUID.Zero)
|
||||||
{
|
{
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,12 +475,12 @@ namespace OpenSim.Region.UserStatistics
|
||||||
usd = uid.session_data;
|
usd = uid.session_data;
|
||||||
|
|
||||||
if (message.Type != OSDType.Map)
|
if (message.Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
|
|
||||||
mmap = (OSDMap)message;
|
mmap = (OSDMap)message;
|
||||||
{
|
{
|
||||||
if (mmap["agent"].Type != OSDType.Map)
|
if (mmap["agent"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
OSDMap agent_map = (OSDMap)mmap["agent"];
|
OSDMap agent_map = (OSDMap)mmap["agent"];
|
||||||
usd.agent_id = agentID;
|
usd.agent_id = agentID;
|
||||||
usd.name_f = uid.name_f;
|
usd.name_f = uid.name_f;
|
||||||
|
@ -493,17 +500,18 @@ namespace OpenSim.Region.UserStatistics
|
||||||
(float)agent_map["fps"].AsReal());
|
(float)agent_map["fps"].AsReal());
|
||||||
|
|
||||||
if (mmap["downloads"].Type != OSDType.Map)
|
if (mmap["downloads"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
OSDMap downloads_map = (OSDMap)mmap["downloads"];
|
OSDMap downloads_map = (OSDMap)mmap["downloads"];
|
||||||
usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal();
|
usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal();
|
||||||
usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal();
|
usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal();
|
||||||
usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal();
|
usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal();
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID());
|
||||||
|
|
||||||
usd.session_id = mmap["session_id"].AsUUID();
|
usd.session_id = mmap["session_id"].AsUUID();
|
||||||
|
|
||||||
if (mmap["system"].Type != OSDType.Map)
|
if (mmap["system"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
OSDMap system_map = (OSDMap)mmap["system"];
|
OSDMap system_map = (OSDMap)mmap["system"];
|
||||||
|
|
||||||
usd.s_cpu = system_map["cpu"].AsString();
|
usd.s_cpu = system_map["cpu"].AsString();
|
||||||
|
@ -512,13 +520,13 @@ namespace OpenSim.Region.UserStatistics
|
||||||
usd.s_ram = system_map["ram"].AsInteger();
|
usd.s_ram = system_map["ram"].AsInteger();
|
||||||
|
|
||||||
if (mmap["stats"].Type != OSDType.Map)
|
if (mmap["stats"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
|
|
||||||
OSDMap stats_map = (OSDMap)mmap["stats"];
|
OSDMap stats_map = (OSDMap)mmap["stats"];
|
||||||
{
|
{
|
||||||
|
|
||||||
if (stats_map["failures"].Type != OSDType.Map)
|
if (stats_map["failures"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
OSDMap stats_failures = (OSDMap)stats_map["failures"];
|
OSDMap stats_failures = (OSDMap)stats_map["failures"];
|
||||||
usd.f_dropped = stats_failures["dropped"].AsInteger();
|
usd.f_dropped = stats_failures["dropped"].AsInteger();
|
||||||
usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
|
usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
|
||||||
|
@ -527,18 +535,18 @@ namespace OpenSim.Region.UserStatistics
|
||||||
usd.f_send_packet = stats_failures["send_packet"].AsInteger();
|
usd.f_send_packet = stats_failures["send_packet"].AsInteger();
|
||||||
|
|
||||||
if (stats_map["net"].Type != OSDType.Map)
|
if (stats_map["net"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
OSDMap stats_net = (OSDMap)stats_map["net"];
|
OSDMap stats_net = (OSDMap)stats_map["net"];
|
||||||
{
|
{
|
||||||
if (stats_net["in"].Type != OSDType.Map)
|
if (stats_net["in"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
|
|
||||||
OSDMap net_in = (OSDMap)stats_net["in"];
|
OSDMap net_in = (OSDMap)stats_net["in"];
|
||||||
usd.n_in_kb = (float)net_in["kbytes"].AsReal();
|
usd.n_in_kb = (float)net_in["kbytes"].AsReal();
|
||||||
usd.n_in_pk = net_in["packets"].AsInteger();
|
usd.n_in_pk = net_in["packets"].AsInteger();
|
||||||
|
|
||||||
if (stats_net["out"].Type != OSDType.Map)
|
if (stats_net["out"].Type != OSDType.Map)
|
||||||
return new UserSessionID();
|
return new UserSession();
|
||||||
OSDMap net_out = (OSDMap)stats_net["out"];
|
OSDMap net_out = (OSDMap)stats_net["out"];
|
||||||
|
|
||||||
usd.n_out_kb = (float)net_out["kbytes"].AsReal();
|
usd.n_out_kb = (float)net_out["kbytes"].AsReal();
|
||||||
|
@ -549,11 +557,18 @@ namespace OpenSim.Region.UserStatistics
|
||||||
|
|
||||||
uid.session_data = usd;
|
uid.session_data = usd;
|
||||||
m_sessions[agentID] = uid;
|
m_sessions[agentID] = uid;
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
|
||||||
|
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUserStats(UserSessionID uid, SqliteConnection db)
|
private void UpdateUserStats(UserSession uid, SqliteConnection db)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
|
||||||
|
|
||||||
if (uid.session_id == UUID.Zero)
|
if (uid.session_id == UUID.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -740,7 +755,6 @@ VALUES
|
||||||
s.min_ping = ArrayMin_f(__ping);
|
s.min_ping = ArrayMin_f(__ping);
|
||||||
s.max_ping = ArrayMax_f(__ping);
|
s.max_ping = ArrayMax_f(__ping);
|
||||||
s.mode_ping = ArrayMode_f(__ping);
|
s.mode_ping = ArrayMode_f(__ping);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Statistics
|
#region Statistics
|
||||||
|
@ -985,7 +999,7 @@ VALUES
|
||||||
}
|
}
|
||||||
#region structs
|
#region structs
|
||||||
|
|
||||||
public struct UserSessionID
|
public class UserSession
|
||||||
{
|
{
|
||||||
public UUID session_id;
|
public UUID session_id;
|
||||||
public UUID region_id;
|
public UUID region_id;
|
||||||
|
|
|
@ -60,7 +60,25 @@ namespace OpenSim.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
string connList = serverConfig.GetString("ServiceConnectors", String.Empty);
|
string connList = serverConfig.GetString("ServiceConnectors", String.Empty);
|
||||||
string[] conns = connList.Split(new char[] {',', ' '});
|
|
||||||
|
IConfig servicesConfig = m_Server.Config.Configs["ServiceList"];
|
||||||
|
if (servicesConfig != null)
|
||||||
|
{
|
||||||
|
List<string> servicesList = new List<string>();
|
||||||
|
if (connList != String.Empty)
|
||||||
|
servicesList.Add(connList);
|
||||||
|
|
||||||
|
foreach (string k in servicesConfig.GetKeys())
|
||||||
|
{
|
||||||
|
string v = servicesConfig.GetString(k);
|
||||||
|
if (v != String.Empty)
|
||||||
|
servicesList.Add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
connList = String.Join(",", servicesList.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] conns = connList.Split(new char[] {',', ' ', '\n', '\r', '\t'});
|
||||||
|
|
||||||
// int i = 0;
|
// int i = 0;
|
||||||
foreach (string c in conns)
|
foreach (string c in conns)
|
||||||
|
|
|
@ -47,6 +47,7 @@ namespace OpenSim.Services.Connectors
|
||||||
|
|
||||||
private string m_ServerURI = String.Empty;
|
private string m_ServerURI = String.Empty;
|
||||||
private IImprovedAssetCache m_Cache = null;
|
private IImprovedAssetCache m_Cache = null;
|
||||||
|
private int m_maxAssetRequestConcurrency = 30;
|
||||||
|
|
||||||
private delegate void AssetRetrievedEx(AssetBase asset);
|
private delegate void AssetRetrievedEx(AssetBase asset);
|
||||||
|
|
||||||
|
@ -71,6 +72,10 @@ namespace OpenSim.Services.Connectors
|
||||||
|
|
||||||
public virtual void Initialise(IConfigSource source)
|
public virtual void Initialise(IConfigSource source)
|
||||||
{
|
{
|
||||||
|
IConfig netconfig = source.Configs["Network"];
|
||||||
|
if (netconfig != null)
|
||||||
|
m_maxAssetRequestConcurrency = netconfig.GetInt("MaxRequestConcurrency",m_maxAssetRequestConcurrency);
|
||||||
|
|
||||||
IConfig assetConfig = source.Configs["AssetService"];
|
IConfig assetConfig = source.Configs["AssetService"];
|
||||||
if (assetConfig == null)
|
if (assetConfig == null)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +113,7 @@ namespace OpenSim.Services.Connectors
|
||||||
if (asset == null)
|
if (asset == null)
|
||||||
{
|
{
|
||||||
asset = SynchronousRestObjectRequester.
|
asset = SynchronousRestObjectRequester.
|
||||||
MakeRequest<int, AssetBase>("GET", uri, 0, 30);
|
MakeRequest<int, AssetBase>("GET", uri, 0, m_maxAssetRequestConcurrency);
|
||||||
|
|
||||||
if (m_Cache != null)
|
if (m_Cache != null)
|
||||||
m_Cache.Cache(asset);
|
m_Cache.Cache(asset);
|
||||||
|
@ -221,7 +226,7 @@ namespace OpenSim.Services.Connectors
|
||||||
m_AssetHandlers.Remove(id);
|
m_AssetHandlers.Remove(id);
|
||||||
}
|
}
|
||||||
handlers.Invoke(a);
|
handlers.Invoke(a);
|
||||||
}, 30);
|
}, m_maxAssetRequestConcurrency);
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ namespace OpenSim.Services.Connectors.Friends
|
||||||
if (!region.ServerURI.EndsWith("/"))
|
if (!region.ServerURI.EndsWith("/"))
|
||||||
path = "/" + path;
|
path = "/" + path;
|
||||||
string uri = region.ServerURI + path;
|
string uri = region.ServerURI + path;
|
||||||
m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
|
// m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -207,7 +207,7 @@ namespace OpenSim.Services.Connectors
|
||||||
if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
|
if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
|
||||||
{
|
{
|
||||||
if (replyData["result"] is Dictionary<string, object>)
|
if (replyData["result"] is Dictionary<string, object>)
|
||||||
guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]);
|
guinfo = Create((Dictionary<string, object>)replyData["result"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return guinfo;
|
return guinfo;
|
||||||
|
@ -273,7 +273,7 @@ namespace OpenSim.Services.Connectors
|
||||||
{
|
{
|
||||||
if (griduser is Dictionary<string, object>)
|
if (griduser is Dictionary<string, object>)
|
||||||
{
|
{
|
||||||
GridUserInfo pinfo = new GridUserInfo((Dictionary<string, object>)griduser);
|
GridUserInfo pinfo = Create((Dictionary<string, object>)griduser);
|
||||||
rinfos.Add(pinfo);
|
rinfos.Add(pinfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -286,5 +286,10 @@ namespace OpenSim.Services.Connectors
|
||||||
|
|
||||||
return rinfos.ToArray();
|
return rinfos.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual GridUserInfo Create(Dictionary<string, object> griduser)
|
||||||
|
{
|
||||||
|
return new GridUserInfo(griduser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,8 +384,8 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
if (response["Success"].AsBoolean())
|
if (response["Success"].AsBoolean())
|
||||||
{
|
{
|
||||||
OSDMap extraData = response["ExtraData"] as OSDMap;
|
OSDMap extraData = response["ExtraData"] as OSDMap;
|
||||||
int enabled = response["Enabled"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.RegionOnline : 0;
|
int enabled = response["Enabled"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.RegionOnline : 0;
|
||||||
int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.Hyperlink : 0;
|
int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.Hyperlink : 0;
|
||||||
int flags = enabled | hypergrid;
|
int flags = enabled | hypergrid;
|
||||||
m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags);
|
m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags);
|
||||||
return flags;
|
return flags;
|
||||||
|
|
|
@ -151,11 +151,11 @@ namespace OpenSim.Services.GridService
|
||||||
//
|
//
|
||||||
// Get it's flags
|
// Get it's flags
|
||||||
//
|
//
|
||||||
OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(region.Data["flags"]);
|
OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(region.Data["flags"]);
|
||||||
|
|
||||||
// Is this a reservation?
|
// Is this a reservation?
|
||||||
//
|
//
|
||||||
if ((rflags & OpenSim.Data.RegionFlags.Reservation) != 0)
|
if ((rflags & OpenSim.Framework.RegionFlags.Reservation) != 0)
|
||||||
{
|
{
|
||||||
// Regions reserved for the null key cannot be taken.
|
// Regions reserved for the null key cannot be taken.
|
||||||
if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString())
|
if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString())
|
||||||
|
@ -166,10 +166,10 @@ namespace OpenSim.Services.GridService
|
||||||
// NOTE: Fudging the flags value here, so these flags
|
// NOTE: Fudging the flags value here, so these flags
|
||||||
// should not be used elsewhere. Don't optimize
|
// should not be used elsewhere. Don't optimize
|
||||||
// this with the later retrieval of the same flags!
|
// this with the later retrieval of the same flags!
|
||||||
rflags |= OpenSim.Data.RegionFlags.Authenticate;
|
rflags |= OpenSim.Framework.RegionFlags.Authenticate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rflags & OpenSim.Data.RegionFlags.Authenticate) != 0)
|
if ((rflags & OpenSim.Framework.RegionFlags.Authenticate) != 0)
|
||||||
{
|
{
|
||||||
// Can we authenticate at all?
|
// Can we authenticate at all?
|
||||||
//
|
//
|
||||||
|
@ -205,10 +205,10 @@ namespace OpenSim.Services.GridService
|
||||||
if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
|
if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
|
||||||
((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
|
((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
|
||||||
{
|
{
|
||||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
|
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.NoMove) != 0)
|
||||||
return "Can't move this region";
|
return "Can't move this region";
|
||||||
|
|
||||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
|
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.LockedOut) != 0)
|
||||||
return "Region locked out";
|
return "Region locked out";
|
||||||
|
|
||||||
// Region reregistering in other coordinates. Delete the old entry
|
// Region reregistering in other coordinates. Delete the old entry
|
||||||
|
@ -233,7 +233,7 @@ namespace OpenSim.Services.GridService
|
||||||
{
|
{
|
||||||
int oldFlags = Convert.ToInt32(region.Data["flags"]);
|
int oldFlags = Convert.ToInt32(region.Data["flags"]);
|
||||||
|
|
||||||
oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation;
|
oldFlags &= ~(int)OpenSim.Framework.RegionFlags.Reservation;
|
||||||
|
|
||||||
rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags
|
rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ namespace OpenSim.Services.GridService
|
||||||
}
|
}
|
||||||
|
|
||||||
int flags = Convert.ToInt32(rdata.Data["flags"]);
|
int flags = Convert.ToInt32(rdata.Data["flags"]);
|
||||||
flags |= (int)OpenSim.Data.RegionFlags.RegionOnline;
|
flags |= (int)OpenSim.Framework.RegionFlags.RegionOnline;
|
||||||
rdata.Data["flags"] = flags.ToString();
|
rdata.Data["flags"] = flags.ToString();
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -283,9 +283,9 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
int flags = Convert.ToInt32(region.Data["flags"]);
|
int flags = Convert.ToInt32(region.Data["flags"]);
|
||||||
|
|
||||||
if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Data.RegionFlags.Persistent) != 0)
|
if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0)
|
||||||
{
|
{
|
||||||
flags &= ~(int)OpenSim.Data.RegionFlags.RegionOnline;
|
flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline;
|
||||||
region.Data["flags"] = flags.ToString();
|
region.Data["flags"] = flags.ToString();
|
||||||
region.Data["last_seen"] = Util.UnixTimeSinceEpoch();
|
region.Data["last_seen"] = Util.UnixTimeSinceEpoch();
|
||||||
try
|
try
|
||||||
|
@ -320,7 +320,7 @@ namespace OpenSim.Services.GridService
|
||||||
if (rdata.RegionID != regionID)
|
if (rdata.RegionID != regionID)
|
||||||
{
|
{
|
||||||
int flags = Convert.ToInt32(rdata.Data["flags"]);
|
int flags = Convert.ToInt32(rdata.Data["flags"]);
|
||||||
if ((flags & (int)Data.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours
|
if ((flags & (int)Framework.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours
|
||||||
rinfos.Add(RegionData2RegionInfo(rdata));
|
rinfos.Add(RegionData2RegionInfo(rdata));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
foreach (RegionData r in regions)
|
foreach (RegionData r in regions)
|
||||||
{
|
{
|
||||||
if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
|
if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
|
||||||
ret.Add(RegionData2RegionInfo(r));
|
ret.Add(RegionData2RegionInfo(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +486,7 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
foreach (RegionData r in regions)
|
foreach (RegionData r in regions)
|
||||||
{
|
{
|
||||||
if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
|
if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
|
||||||
ret.Add(RegionData2RegionInfo(r));
|
ret.Add(RegionData2RegionInfo(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +502,7 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
foreach (RegionData r in regions)
|
foreach (RegionData r in regions)
|
||||||
{
|
{
|
||||||
if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
|
if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
|
||||||
ret.Add(RegionData2RegionInfo(r));
|
ret.Add(RegionData2RegionInfo(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +629,7 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
private void OutputRegionToConsole(RegionData r)
|
private void OutputRegionToConsole(RegionData r)
|
||||||
{
|
{
|
||||||
OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]);
|
OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
|
||||||
|
|
||||||
ConsoleDisplayList dispList = new ConsoleDisplayList();
|
ConsoleDisplayList dispList = new ConsoleDisplayList();
|
||||||
dispList.AddRow("Region Name", r.RegionName);
|
dispList.AddRow("Region Name", r.RegionName);
|
||||||
|
@ -659,7 +659,7 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
foreach (RegionData r in regions)
|
foreach (RegionData r in regions)
|
||||||
{
|
{
|
||||||
OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]);
|
OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
|
||||||
dispTable.AddRow(
|
dispTable.AddRow(
|
||||||
r.RegionName,
|
r.RegionName,
|
||||||
r.RegionID.ToString(),
|
r.RegionID.ToString(),
|
||||||
|
@ -673,7 +673,7 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
private int ParseFlags(int prev, string flags)
|
private int ParseFlags(int prev, string flags)
|
||||||
{
|
{
|
||||||
OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)prev;
|
OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)prev;
|
||||||
|
|
||||||
string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
|
string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
@ -685,18 +685,18 @@ namespace OpenSim.Services.GridService
|
||||||
{
|
{
|
||||||
if (p.StartsWith("+"))
|
if (p.StartsWith("+"))
|
||||||
{
|
{
|
||||||
val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1));
|
val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
|
||||||
f |= (OpenSim.Data.RegionFlags)val;
|
f |= (OpenSim.Framework.RegionFlags)val;
|
||||||
}
|
}
|
||||||
else if (p.StartsWith("-"))
|
else if (p.StartsWith("-"))
|
||||||
{
|
{
|
||||||
val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1));
|
val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
|
||||||
f &= ~(OpenSim.Data.RegionFlags)val;
|
f &= ~(OpenSim.Framework.RegionFlags)val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p);
|
val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p);
|
||||||
f |= (OpenSim.Data.RegionFlags)val;
|
f |= (OpenSim.Framework.RegionFlags)val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
@ -728,7 +728,7 @@ namespace OpenSim.Services.GridService
|
||||||
int flags = Convert.ToInt32(r.Data["flags"]);
|
int flags = Convert.ToInt32(r.Data["flags"]);
|
||||||
flags = ParseFlags(flags, cmd[4]);
|
flags = ParseFlags(flags, cmd[4]);
|
||||||
r.Data["flags"] = flags.ToString();
|
r.Data["flags"] = flags.ToString();
|
||||||
OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)flags;
|
OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)flags;
|
||||||
|
|
||||||
MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f));
|
MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f));
|
||||||
m_Database.Store(r);
|
m_Database.Store(r);
|
||||||
|
|
|
@ -390,8 +390,8 @@ namespace OpenSim.Services.GridService
|
||||||
List<RegionData> regions = m_Database.Get(mapName, m_ScopeID);
|
List<RegionData> regions = m_Database.Get(mapName, m_ScopeID);
|
||||||
if (regions != null && regions.Count > 0)
|
if (regions != null && regions.Count > 0)
|
||||||
{
|
{
|
||||||
OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
|
OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
|
||||||
if ((rflags & OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
if ((rflags & OpenSim.Framework.RegionFlags.Hyperlink) != 0)
|
||||||
{
|
{
|
||||||
regInfo = new GridRegion();
|
regInfo = new GridRegion();
|
||||||
regInfo.RegionID = regions[0].RegionID;
|
regInfo.RegionID = regions[0].RegionID;
|
||||||
|
@ -460,7 +460,7 @@ namespace OpenSim.Services.GridService
|
||||||
private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle)
|
private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle)
|
||||||
{
|
{
|
||||||
RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo);
|
RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo);
|
||||||
int flags = (int)OpenSim.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline;
|
int flags = (int)OpenSim.Framework.RegionFlags.Hyperlink + (int)OpenSim.Framework.RegionFlags.NoDirectLogin + (int)OpenSim.Framework.RegionFlags.RegionOnline;
|
||||||
rdata.Data["flags"] = flags.ToString();
|
rdata.Data["flags"] = flags.ToString();
|
||||||
|
|
||||||
m_Database.Store(rdata);
|
m_Database.Store(rdata);
|
||||||
|
|
|
@ -100,6 +100,19 @@ namespace OpenSim.Services.Interfaces
|
||||||
List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
|
List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
|
||||||
List<GridRegion> GetHyperlinks(UUID scopeID);
|
List<GridRegion> GetHyperlinks(UUID scopeID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get internal OpenSimulator region flags.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// See OpenSimulator.Framework.RegionFlags. These are not returned in the GridRegion structure -
|
||||||
|
/// they currently need to be requested separately. Possibly this should change to avoid multiple service calls
|
||||||
|
/// in some situations.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// The region flags.
|
||||||
|
/// </returns>
|
||||||
|
/// <param name='scopeID'></param>
|
||||||
|
/// <param name='regionID'></param>
|
||||||
int GetRegionFlags(UUID scopeID, UUID regionID);
|
int GetRegionFlags(UUID scopeID, UUID regionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace OpenSim.Services.Interfaces
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, object> ToKeyValuePairs()
|
public virtual Dictionary<string, object> ToKeyValuePairs()
|
||||||
{
|
{
|
||||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
result["UserID"] = UserID;
|
result["UserID"] = UserID;
|
||||||
|
|
|
@ -293,7 +293,7 @@ namespace OpenSim.Services.LLLoginService
|
||||||
{
|
{
|
||||||
m_log.InfoFormat(
|
m_log.InfoFormat(
|
||||||
"[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}",
|
"[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}",
|
||||||
firstName, lastName, m_MinLoginLevel, account.UserLevel);
|
firstName, lastName, account.UserLevel, m_MinLoginLevel);
|
||||||
return LLFailedLoginResponse.LoginBlockedProblem;
|
return LLFailedLoginResponse.LoginBlockedProblem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -427,6 +427,10 @@
|
||||||
; " (Mozilla Compatible)" to the text where there are problems with a web server
|
; " (Mozilla Compatible)" to the text where there are problems with a web server
|
||||||
;user_agent = "OpenSim LSL (Mozilla Compatible)"
|
;user_agent = "OpenSim LSL (Mozilla Compatible)"
|
||||||
|
|
||||||
|
; OpenSim can send multiple simultaneous requests for services such as asset
|
||||||
|
; retrieval. However, some versions of mono appear to hang when there are too
|
||||||
|
; many simultaneous requests, default is 30 and is currently applied only to assets
|
||||||
|
;MaxRequestConcurrency = 30
|
||||||
|
|
||||||
[XMLRPC]
|
[XMLRPC]
|
||||||
; ##
|
; ##
|
||||||
|
@ -840,6 +844,15 @@
|
||||||
; When the avatar flies, it will be moved up by this amount off the ground (in meters)
|
; When the avatar flies, it will be moved up by this amount off the ground (in meters)
|
||||||
minimum_ground_flight_offset = 3.0
|
minimum_ground_flight_offset = 3.0
|
||||||
|
|
||||||
|
; Plant avatar. This reduces the effect of physical contacts with the avatar.
|
||||||
|
; If you have a group of unruly and rude visitors that bump each other, turn this on to make that less attractive.
|
||||||
|
; The avatar still allows a small movement based on the PID settings above. Stronger PID settings AND this active
|
||||||
|
; will lock the avatar in place
|
||||||
|
av_planted = false
|
||||||
|
|
||||||
|
; No Avatar Avatar Collissions. This causes avatar to be able to walk through each other as if they're ghosts but still interact with the environment
|
||||||
|
av_av_collisions_off = false
|
||||||
|
|
||||||
; ##
|
; ##
|
||||||
; ## Object options
|
; ## Object options
|
||||||
; ##
|
; ##
|
||||||
|
@ -1589,10 +1602,14 @@
|
||||||
|
|
||||||
|
|
||||||
[PacketPool]
|
[PacketPool]
|
||||||
; Enables the experimental packet pool. Yes, we've been here before.
|
|
||||||
;RecyclePackets = true;
|
;RecyclePackets = true;
|
||||||
;RecycleDataBlocks = true;
|
;RecycleDataBlocks = true;
|
||||||
|
|
||||||
|
; If true, then the basic packet objects used to receive data are also recycled, not just the LLUDP packets.
|
||||||
|
; This reduces data churn
|
||||||
|
; This setting is currently experimental and defaults to false.
|
||||||
|
RecycleBaseUDPPackets = false;
|
||||||
|
|
||||||
|
|
||||||
[InterestManagement]
|
[InterestManagement]
|
||||||
; This section controls how state updates are prioritized for each client
|
; This section controls how state updates are prioritized for each client
|
||||||
|
|
|
@ -20,8 +20,38 @@
|
||||||
; * The full syntax of a connector string is:
|
; * The full syntax of a connector string is:
|
||||||
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
||||||
; *
|
; *
|
||||||
[Startup]
|
|
||||||
ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector,8002/OpenSim.Server.Handlers.dll:IntegrationServiceConnector"
|
[ServiceList]
|
||||||
|
|
||||||
|
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||||
|
InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
|
||||||
|
VoiceConnector = "8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector"
|
||||||
|
GridServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridServiceConnector"
|
||||||
|
GridInfoServerInConnector = "8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector"
|
||||||
|
AuthenticationServiceConnector = "8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector"
|
||||||
|
OpenIdServerConnector = "8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector"
|
||||||
|
AvatarServiceConnector = "8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector"
|
||||||
|
LLLoginServiceInConnector = "8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector"
|
||||||
|
PresenceServiceConnector = "8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector"
|
||||||
|
UserAccountServiceConnector = "8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector"
|
||||||
|
GridUserServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector"
|
||||||
|
FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
|
||||||
|
MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
|
||||||
|
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
||||||
|
|
||||||
|
;; Additions for Hypergrid
|
||||||
|
|
||||||
|
GatekeeperServiceInConnector = "8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector"
|
||||||
|
UserAgentServerConnector = "8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector"
|
||||||
|
HeloServiceInConnector = "8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector"
|
||||||
|
HGFriendsServerConnector = "8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector"
|
||||||
|
InstantMessageServerConnector = "8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector"
|
||||||
|
HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector"
|
||||||
|
HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||||
|
|
||||||
|
;; Additions for other add-on modules. For example:
|
||||||
|
;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
|
||||||
|
IntegrationService = "8002/OpenSim.Server.Handlers.dll:IntegrationServiceConnector"
|
||||||
|
|
||||||
; * This is common for all services, it's the network setup for the entire
|
; * This is common for all services, it's the network setup for the entire
|
||||||
; * server instance, if none is specified above
|
; * server instance, if none is specified above
|
||||||
|
|
|
@ -13,8 +13,24 @@
|
||||||
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
||||||
; *
|
; *
|
||||||
[Startup]
|
[Startup]
|
||||||
ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector,8002/OpenSim.Server.Handlers.dll:IntegrationServiceConnector"
|
|
||||||
|
|
||||||
|
[ServiceList]
|
||||||
|
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||||
|
InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
|
||||||
|
VoiceConnector = "8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector"
|
||||||
|
GridServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridServiceConnector"
|
||||||
|
GridInfoServerInConnector = "8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector"
|
||||||
|
AuthenticationServiceConnector = "8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector"
|
||||||
|
OpenIdServerConnector = "8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector"
|
||||||
|
AvatarServiceConnector = "8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector"
|
||||||
|
LLLoginServiceInConnector = "8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector"
|
||||||
|
PresenceServiceConnector = "8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector"
|
||||||
|
UserAccountServiceConnector = "8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector"
|
||||||
|
GridUserServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector"
|
||||||
|
FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
|
||||||
|
MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
|
||||||
|
MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
|
||||||
|
IntegrationService = "8002/OpenSim.Server.Handlers.dll:IntegrationServiceConnector"
|
||||||
; * This is common for all services, it's the network setup for the entire
|
; * This is common for all services, it's the network setup for the entire
|
||||||
; * server instance, if none is specified above
|
; * server instance, if none is specified above
|
||||||
; *
|
; *
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
265
prebuild.xml
265
prebuild.xml
|
@ -112,6 +112,34 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project frameworkVersion="v3_5" name="OpenSim.Services.Interfaces" path="OpenSim/Services/Interfaces" 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"/>
|
||||||
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
||||||
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Framework.Monitoring" path="OpenSim/Framework/Monitoring" type="Library">
|
<Project frameworkVersion="v3_5" name="OpenSim.Framework.Monitoring" path="OpenSim/Framework/Monitoring" type="Library">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
<Options>
|
<Options>
|
||||||
|
@ -205,34 +233,6 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Services.Interfaces" path="OpenSim/Services/Interfaces" 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"/>
|
|
||||||
<Reference name="OpenSim.Framework.Console"/>
|
|
||||||
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
|
||||||
<Reference name="Nini" path="../../../bin/"/>
|
|
||||||
<Reference name="log4net" path="../../../bin/"/>
|
|
||||||
|
|
||||||
<Files>
|
|
||||||
<Match pattern="*.cs" recurse="true"/>
|
|
||||||
</Files>
|
|
||||||
</Project>
|
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Framework.Serialization" path="OpenSim/Framework/Serialization" type="Library">
|
<Project frameworkVersion="v3_5" name="OpenSim.Framework.Serialization" path="OpenSim/Framework/Serialization" type="Library">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
<Options>
|
<Options>
|
||||||
|
@ -1415,110 +1415,6 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library">
|
|
||||||
<Configuration name="Debug">
|
|
||||||
<Options>
|
|
||||||
<OutputPath>../../../bin/</OutputPath>
|
|
||||||
<AllowUnsafe>true</AllowUnsafe>
|
|
||||||
</Options>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration name="Release">
|
|
||||||
<Options>
|
|
||||||
<OutputPath>../../../bin/</OutputPath>
|
|
||||||
<AllowUnsafe>true</AllowUnsafe>
|
|
||||||
</Options>
|
|
||||||
</Configuration>
|
|
||||||
|
|
||||||
<ReferencePath>../../../bin/</ReferencePath>
|
|
||||||
<Reference name="System"/>
|
|
||||||
<Reference name="System.Core"/>
|
|
||||||
<Reference name="System.Xml"/>
|
|
||||||
<Reference name="System.Xml.Linq"/>
|
|
||||||
<Reference name="System.Drawing"/>
|
|
||||||
<Reference name="System.Web"/>
|
|
||||||
<Reference name="NDesk.Options" path="../../../bin/"/>
|
|
||||||
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
|
||||||
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
|
||||||
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
|
||||||
<Reference name="CSJ2K" path="../../../bin/"/>
|
|
||||||
<Reference name="Warp3D" path="../../../bin/"/>
|
|
||||||
<Reference name="OpenSim.Capabilities"/>
|
|
||||||
<Reference name="OpenSim.Data"/>
|
|
||||||
<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.Region.Framework"/>
|
|
||||||
<Reference name="OpenSim.Region.Physics.Manager"/>
|
|
||||||
<Reference name="OpenSim.Server.Base"/>
|
|
||||||
<Reference name="OpenSim.Server.Handlers"/>
|
|
||||||
<Reference name="OpenSim.Services.Connectors"/>
|
|
||||||
<Reference name="OpenSim.Services.Base"/>
|
|
||||||
<Reference name="OpenSim.Services.Interfaces"/>
|
|
||||||
<Reference name="Ionic.Zip" path="../../../bin/"/>
|
|
||||||
|
|
||||||
<Reference name="GlynnTucker.Cache" path="../../../bin/"/>
|
|
||||||
|
|
||||||
<!-- For scripting in funny languages by default -->
|
|
||||||
<Reference name="XMLRPC" path="../../../bin/"/>
|
|
||||||
<Reference name="OpenSim.Framework.Communications"/>
|
|
||||||
<Reference name="Nini" path="../../../bin/"/>
|
|
||||||
<Reference name="log4net" path="../../../bin/"/>
|
|
||||||
<Reference name="DotNetOpenMail" path="../../../bin/"/>
|
|
||||||
|
|
||||||
<!-- To allow regions to have mono addins -->
|
|
||||||
<Reference name="Mono.Addins" path="../../../bin/"/>
|
|
||||||
|
|
||||||
<Files>
|
|
||||||
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
|
|
||||||
<Match pattern="*.cs" recurse="true">
|
|
||||||
<Exclude name="Tests" pattern="Tests"/>
|
|
||||||
</Match>
|
|
||||||
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
|
|
||||||
</Files>
|
|
||||||
</Project>
|
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Region.RegionCombinerModule" path="OpenSim/Region/RegionCombinerModule" 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.Xml"/>
|
|
||||||
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
|
||||||
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
|
||||||
<Reference name="OpenSim.Framework"/>
|
|
||||||
<Reference name="OpenSim.Framework.Communications"/>
|
|
||||||
<Reference name="OpenSim.Region.Framework"/>
|
|
||||||
<Reference name="OpenSim.Server.Base"/>
|
|
||||||
<Reference name="OpenSim.Server.Handlers"/>
|
|
||||||
<Reference name="OpenSim.Framework.Console"/>
|
|
||||||
<Reference name="OpenSim.Region.Physics.Manager"/>
|
|
||||||
<Reference name="OpenSim.Framework.Communications"/>
|
|
||||||
<Reference name="OpenSim.Region.CoreModules"/>
|
|
||||||
<Reference name="Nini" path="../../../bin/"/>
|
|
||||||
<Reference name="log4net" path="../../../bin/"/>
|
|
||||||
|
|
||||||
<!-- To allow regions to have mono addins -->
|
|
||||||
<Reference name="Mono.Addins" path="../../../bin/"/>
|
|
||||||
|
|
||||||
<Files>
|
|
||||||
<Match pattern="*.cs" recurse="true"/>
|
|
||||||
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
|
|
||||||
</Files>
|
|
||||||
</Project>
|
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Region.ClientStack" path="OpenSim/Region/ClientStack" type="Library">
|
<Project frameworkVersion="v3_5" name="OpenSim.Region.ClientStack" path="OpenSim/Region/ClientStack" type="Library">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
<Options>
|
<Options>
|
||||||
|
@ -1639,6 +1535,111 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
<AllowUnsafe>true</AllowUnsafe>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
<AllowUnsafe>true</AllowUnsafe>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../../bin/</ReferencePath>
|
||||||
|
<Reference name="System"/>
|
||||||
|
<Reference name="System.Core"/>
|
||||||
|
<Reference name="System.Xml"/>
|
||||||
|
<Reference name="System.Xml.Linq"/>
|
||||||
|
<Reference name="System.Drawing"/>
|
||||||
|
<Reference name="System.Web"/>
|
||||||
|
<Reference name="NDesk.Options" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||||
|
<Reference name="CSJ2K" path="../../../bin/"/>
|
||||||
|
<Reference name="Warp3D" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenSim.Capabilities"/>
|
||||||
|
<Reference name="OpenSim.Data"/>
|
||||||
|
<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.Region.ClientStack.LindenUDP"/>
|
||||||
|
<Reference name="OpenSim.Region.Framework"/>
|
||||||
|
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||||
|
<Reference name="OpenSim.Server.Base"/>
|
||||||
|
<Reference name="OpenSim.Server.Handlers"/>
|
||||||
|
<Reference name="OpenSim.Services.Connectors"/>
|
||||||
|
<Reference name="OpenSim.Services.Base"/>
|
||||||
|
<Reference name="OpenSim.Services.Interfaces"/>
|
||||||
|
<Reference name="Ionic.Zip" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<Reference name="GlynnTucker.Cache" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<!-- For scripting in funny languages by default -->
|
||||||
|
<Reference name="XMLRPC" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenSim.Framework.Communications"/>
|
||||||
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
<Reference name="DotNetOpenMail" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<!-- To allow regions to have mono addins -->
|
||||||
|
<Reference name="Mono.Addins" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
|
||||||
|
<Match pattern="*.cs" recurse="true">
|
||||||
|
<Exclude name="Tests" pattern="Tests"/>
|
||||||
|
</Match>
|
||||||
|
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
|
<Project frameworkVersion="v3_5" name="OpenSim.Region.RegionCombinerModule" path="OpenSim/Region/RegionCombinerModule" 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.Xml"/>
|
||||||
|
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||||
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Framework.Communications"/>
|
||||||
|
<Reference name="OpenSim.Region.Framework"/>
|
||||||
|
<Reference name="OpenSim.Server.Base"/>
|
||||||
|
<Reference name="OpenSim.Server.Handlers"/>
|
||||||
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||||
|
<Reference name="OpenSim.Framework.Communications"/>
|
||||||
|
<Reference name="OpenSim.Region.CoreModules"/>
|
||||||
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<!-- To allow regions to have mono addins -->
|
||||||
|
<Reference name="Mono.Addins" path="../../../bin/"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true"/>
|
||||||
|
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.Region.OptionalModules" path="OpenSim/Region/OptionalModules" type="Library">
|
<Project frameworkVersion="v3_5" name="OpenSim.Region.OptionalModules" path="OpenSim/Region/OptionalModules" type="Library">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
<Options>
|
<Options>
|
||||||
|
|
Loading…
Reference in New Issue