Merge branch 'master' into careminster-presence-refactor
commit
42b96a8be0
|
@ -66,8 +66,8 @@ namespace OpenSim.Client.MXP.ClientStack
|
||||||
private readonly IScene m_scene;
|
private readonly IScene m_scene;
|
||||||
private readonly string m_firstName;
|
private readonly string m_firstName;
|
||||||
private readonly string m_lastName;
|
private readonly string m_lastName;
|
||||||
private int m_objectsToSynchronize = 0;
|
// private int m_objectsToSynchronize = 0;
|
||||||
private int m_objectsSynchronized = -1;
|
// private int m_objectsSynchronized = -1;
|
||||||
|
|
||||||
private Vector3 m_startPosition=new Vector3(128f, 128f, 128f);
|
private Vector3 m_startPosition=new Vector3(128f, 128f, 128f);
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -462,8 +462,8 @@ namespace OpenSim.Client.MXP.ClientStack
|
||||||
|
|
||||||
public void MXPSendSynchronizationBegin(int objectCount)
|
public void MXPSendSynchronizationBegin(int objectCount)
|
||||||
{
|
{
|
||||||
m_objectsToSynchronize = objectCount;
|
// m_objectsToSynchronize = objectCount;
|
||||||
m_objectsSynchronized = 0;
|
// m_objectsSynchronized = 0;
|
||||||
SynchronizationBeginEventMessage synchronizationBeginEventMessage = new SynchronizationBeginEventMessage();
|
SynchronizationBeginEventMessage synchronizationBeginEventMessage = new SynchronizationBeginEventMessage();
|
||||||
synchronizationBeginEventMessage.ObjectCount = (uint)objectCount;
|
synchronizationBeginEventMessage.ObjectCount = (uint)objectCount;
|
||||||
Session.Send(synchronizationBeginEventMessage);
|
Session.Send(synchronizationBeginEventMessage);
|
||||||
|
|
|
@ -39,6 +39,8 @@ namespace OpenSim.Data.MySQL
|
||||||
{
|
{
|
||||||
public class MySQLGenericTableHandler<T> : MySqlFramework where T: class, new()
|
public class MySQLGenericTableHandler<T> : MySqlFramework where T: class, new()
|
||||||
{
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
protected Dictionary<string, FieldInfo> m_Fields =
|
protected Dictionary<string, FieldInfo> m_Fields =
|
||||||
new Dictionary<string, FieldInfo>();
|
new Dictionary<string, FieldInfo>();
|
||||||
|
|
||||||
|
@ -217,7 +219,6 @@ namespace OpenSim.Data.MySQL
|
||||||
{
|
{
|
||||||
using (MySqlCommand cmd = new MySqlCommand())
|
using (MySqlCommand cmd = new MySqlCommand())
|
||||||
{
|
{
|
||||||
|
|
||||||
string query = "";
|
string query = "";
|
||||||
List<String> names = new List<String>();
|
List<String> names = new List<String>();
|
||||||
List<String> values = new List<String>();
|
List<String> values = new List<String>();
|
||||||
|
@ -226,6 +227,16 @@ namespace OpenSim.Data.MySQL
|
||||||
{
|
{
|
||||||
names.Add(fi.Name);
|
names.Add(fi.Name);
|
||||||
values.Add("?" + fi.Name);
|
values.Add("?" + fi.Name);
|
||||||
|
|
||||||
|
// Temporarily return more information about what field is unexpectedly null for
|
||||||
|
// http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the
|
||||||
|
// InventoryTransferModule or we may be required to substitute a DBNull here.
|
||||||
|
if (fi.GetValue(row) == null)
|
||||||
|
throw new NullReferenceException(
|
||||||
|
string.Format(
|
||||||
|
"[MYSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",
|
||||||
|
fi.Name, row));
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue(fi.Name, fi.GetValue(row).ToString());
|
cmd.Parameters.AddWithValue(fi.Name, fi.GetValue(row).ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -341,7 +341,12 @@ namespace OpenSim
|
||||||
|
|
||||||
m_console.Commands.AddCommand("region", false, "config get",
|
m_console.Commands.AddCommand("region", false, "config get",
|
||||||
"config get [<section>] [<key>]",
|
"config get [<section>] [<key>]",
|
||||||
"Show a config option",
|
"Synonym for config show",
|
||||||
|
HandleConfig);
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand("region", false, "config show",
|
||||||
|
"config show [<section>] [<key>]",
|
||||||
|
"Show config information",
|
||||||
"If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
|
"If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
|
||||||
+ "If a section is given but not a field, then all fields in that section are printed.",
|
+ "If a section is given but not a field, then all fields in that section are printed.",
|
||||||
HandleConfig);
|
HandleConfig);
|
||||||
|
@ -593,7 +598,9 @@ namespace OpenSim
|
||||||
|
|
||||||
if (cmdparams.Length > 0)
|
if (cmdparams.Length > 0)
|
||||||
{
|
{
|
||||||
switch (cmdparams[0].ToLower())
|
string firstParam = cmdparams[0].ToLower();
|
||||||
|
|
||||||
|
switch (firstParam)
|
||||||
{
|
{
|
||||||
case "set":
|
case "set":
|
||||||
if (cmdparams.Length < 4)
|
if (cmdparams.Length < 4)
|
||||||
|
@ -618,6 +625,7 @@ namespace OpenSim
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "get":
|
case "get":
|
||||||
|
case "show":
|
||||||
if (cmdparams.Length == 1)
|
if (cmdparams.Length == 1)
|
||||||
{
|
{
|
||||||
foreach (IConfig config in m_config.Source.Configs)
|
foreach (IConfig config in m_config.Source.Configs)
|
||||||
|
@ -654,8 +662,8 @@ namespace OpenSim
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Notice("Syntax: config get [<section>] [<key>]");
|
Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
|
||||||
Notice("Example: config get ScriptEngine.DotNetEngine NumberOfScriptThreads");
|
Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -49,6 +49,8 @@ using Timer = System.Timers.Timer;
|
||||||
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
using AssetLandmark = OpenSim.Framework.AssetLandmark;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace OpenSim.Region.ClientStack.LindenUDP
|
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
|
public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
|
||||||
|
@ -299,6 +301,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
|
/// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
|
||||||
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
|
private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
|
||||||
|
|
||||||
|
// First log file or time has expired, start writing to a new log file
|
||||||
|
//<MIC>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// THIS IS DEBUGGING CODE & SHOULD BE REMOVED
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public class QueueLogger
|
||||||
|
{
|
||||||
|
public Int32 start = 0;
|
||||||
|
public StreamWriter Log = null;
|
||||||
|
private Dictionary<UUID,int> m_idMap = new Dictionary<UUID,int>();
|
||||||
|
|
||||||
|
public QueueLogger()
|
||||||
|
{
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
String fname = String.Format("queue-{0}.log", now.ToString("yyyyMMddHHmmss"));
|
||||||
|
Log = new StreamWriter(fname);
|
||||||
|
|
||||||
|
start = Util.EnvironmentTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int LookupID(UUID uuid)
|
||||||
|
{
|
||||||
|
int localid;
|
||||||
|
if (! m_idMap.TryGetValue(uuid,out localid))
|
||||||
|
{
|
||||||
|
localid = m_idMap.Count + 1;
|
||||||
|
m_idMap[uuid] = localid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return localid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueueLogger QueueLog = null;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void LogAvatarUpdateEvent(UUID client, UUID avatar, Int32 timeinqueue)
|
||||||
|
{
|
||||||
|
if (QueueLog == null)
|
||||||
|
QueueLog = new QueueLogger();
|
||||||
|
|
||||||
|
Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
|
||||||
|
lock(QueueLog)
|
||||||
|
{
|
||||||
|
int cid = QueueLog.LookupID(client);
|
||||||
|
int aid = QueueLog.LookupID(avatar);
|
||||||
|
QueueLog.Log.WriteLine("{0},AU,AV{1:D4},AV{2:D4},{3}",ticks,cid,aid,timeinqueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void LogQueueProcessEvent(UUID client, PriorityQueue queue, uint maxup)
|
||||||
|
{
|
||||||
|
if (QueueLog == null)
|
||||||
|
QueueLog = new QueueLogger();
|
||||||
|
|
||||||
|
Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
|
||||||
|
lock(QueueLog)
|
||||||
|
{
|
||||||
|
int cid = QueueLog.LookupID(client);
|
||||||
|
QueueLog.Log.WriteLine("{0},PQ,AV{1:D4},{2},{3}",ticks,cid,maxup,queue.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
//</MIC>
|
||||||
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
|
protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
|
||||||
|
|
||||||
|
@ -3575,6 +3648,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
#region Primitive Packet/Data Sending Methods
|
#region Primitive Packet/Data Sending Methods
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate one of the object update packets based on PrimUpdateFlags
|
/// Generate one of the object update packets based on PrimUpdateFlags
|
||||||
/// and broadcast the packet to clients
|
/// and broadcast the packet to clients
|
||||||
|
@ -3590,12 +3664,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return; // Don't send updates for other people's HUDs
|
return; // Don't send updates for other people's HUDs
|
||||||
}
|
}
|
||||||
|
|
||||||
double priority = m_prioritizer.GetUpdatePriority(this, entity);
|
uint priority = m_prioritizer.GetUpdatePriority(this, entity);
|
||||||
|
|
||||||
lock (m_entityUpdates.SyncRoot)
|
lock (m_entityUpdates.SyncRoot)
|
||||||
m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation), entity.LocalId);
|
m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Int32 m_LastQueueFill = 0;
|
||||||
|
private uint m_maxUpdates = 0;
|
||||||
|
|
||||||
private void ProcessEntityUpdates(int maxUpdates)
|
private void ProcessEntityUpdates(int maxUpdates)
|
||||||
{
|
{
|
||||||
OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
|
OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
|
||||||
|
@ -3603,195 +3680,232 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
||||||
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
|
||||||
|
|
||||||
if (maxUpdates <= 0) maxUpdates = Int32.MaxValue;
|
if (maxUpdates <= 0)
|
||||||
int updatesThisCall = 0;
|
|
||||||
|
|
||||||
float avgTimeDilation = 0;
|
|
||||||
|
|
||||||
EntityUpdate update;
|
|
||||||
while (updatesThisCall < maxUpdates)
|
|
||||||
{
|
{
|
||||||
lock (m_entityUpdates.SyncRoot)
|
m_maxUpdates = Int32.MaxValue;
|
||||||
if (!m_entityUpdates.TryDequeue(out update))
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
avgTimeDilation += update.TimeDilation;
|
if (m_maxUpdates == 0 || m_LastQueueFill == 0)
|
||||||
avgTimeDilation *= 0.5f;
|
|
||||||
|
|
||||||
if (update.Entity is SceneObjectPart)
|
|
||||||
{
|
{
|
||||||
SceneObjectPart part = (SceneObjectPart)update.Entity;
|
m_maxUpdates = (uint)maxUpdates;
|
||||||
|
|
||||||
// Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
|
|
||||||
// will never receive an update after a prim kill. Even then, keeping the kill record may be a good
|
|
||||||
// safety measure.
|
|
||||||
//
|
|
||||||
// If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
|
|
||||||
// after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
|
|
||||||
// updates and kills on different threads with different scheduling strategies, hence this protection.
|
|
||||||
//
|
|
||||||
// This doesn't appear to apply to child prims - a client will happily ignore these updates
|
|
||||||
// after the root prim has been deleted.
|
|
||||||
lock (m_killRecord)
|
|
||||||
{
|
|
||||||
if (m_killRecord.Contains(part.LocalId))
|
|
||||||
continue;
|
|
||||||
if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (part.ParentGroup.IsDeleted)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (part.ParentGroup.IsAttachment)
|
|
||||||
{ // Someone else's HUD, why are we getting these?
|
|
||||||
if (part.ParentGroup.OwnerID != AgentId &&
|
|
||||||
part.ParentGroup.RootPart.Shape.State >= 30)
|
|
||||||
continue;
|
|
||||||
ScenePresence sp;
|
|
||||||
// Owner is not in the sim, don't update it to
|
|
||||||
// anyone
|
|
||||||
if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
List<SceneObjectGroup> atts = sp.Attachments;
|
|
||||||
bool found = false;
|
|
||||||
foreach (SceneObjectGroup att in atts)
|
|
||||||
{
|
|
||||||
if (att == part.ParentGroup)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's an attachment of a valid avatar, but
|
|
||||||
// doesn't seem to be attached, skip
|
|
||||||
if (!found)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (part.ParentGroup.IsAttachment && m_disableFacelights)
|
|
||||||
{
|
|
||||||
if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
|
|
||||||
part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
|
|
||||||
{
|
|
||||||
part.Shape.LightEntry = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++updatesThisCall;
|
|
||||||
|
|
||||||
#region UpdateFlags to packet type conversion
|
|
||||||
|
|
||||||
PrimUpdateFlags updateFlags = update.Flags;
|
|
||||||
|
|
||||||
bool canUseCompressed = true;
|
|
||||||
bool canUseImproved = true;
|
|
||||||
|
|
||||||
// Compressed object updates only make sense for LL primitives
|
|
||||||
if (!(update.Entity is SceneObjectPart))
|
|
||||||
{
|
|
||||||
canUseCompressed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
|
|
||||||
{
|
|
||||||
canUseCompressed = false;
|
|
||||||
canUseImproved = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
|
if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
|
m_maxUpdates += 5;
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
|
else
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Joint))
|
m_maxUpdates = m_maxUpdates >> 1;
|
||||||
|
}
|
||||||
|
m_maxUpdates = Util.Clamp<uint>(m_maxUpdates,10,500);
|
||||||
|
}
|
||||||
|
m_LastQueueFill = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
|
int updatesThisCall = 0;
|
||||||
|
|
||||||
|
//<MIC>
|
||||||
|
// DEBUGGING CODE... REMOVE
|
||||||
|
// LogQueueProcessEvent(this.m_agentId,m_entityUpdates,m_maxUpdates);
|
||||||
|
//</MIC>
|
||||||
|
// We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
|
||||||
|
// condition where a kill can be processed before an out-of-date update for the same object.
|
||||||
|
float avgTimeDilation = 1.0f;
|
||||||
|
|
||||||
|
lock (m_killRecord)
|
||||||
|
{
|
||||||
|
EntityUpdate update;
|
||||||
|
Int32 timeinqueue; // this is just debugging code & can be dropped later
|
||||||
|
|
||||||
|
while (updatesThisCall < m_maxUpdates)
|
||||||
|
{
|
||||||
|
lock (m_entityUpdates.SyncRoot)
|
||||||
|
if (!m_entityUpdates.TryDequeue(out update, out timeinqueue))
|
||||||
|
break;
|
||||||
|
avgTimeDilation += update.TimeDilation;
|
||||||
|
avgTimeDilation *= 0.5f;
|
||||||
|
|
||||||
|
if (update.Entity is SceneObjectPart)
|
||||||
|
{
|
||||||
|
SceneObjectPart part = (SceneObjectPart)update.Entity;
|
||||||
|
|
||||||
|
// Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
|
||||||
|
// will never receive an update after a prim kill. Even then, keeping the kill record may be a good
|
||||||
|
// safety measure.
|
||||||
|
//
|
||||||
|
// If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
|
||||||
|
// after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
|
||||||
|
// updates and kills on different threads with different scheduling strategies, hence this protection.
|
||||||
|
//
|
||||||
|
// This doesn't appear to apply to child prims - a client will happily ignore these updates
|
||||||
|
// after the root prim has been deleted.
|
||||||
|
lock (m_killRecord)
|
||||||
|
{
|
||||||
|
if (m_killRecord.Contains(part.LocalId))
|
||||||
|
continue;
|
||||||
|
if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.ParentGroup.IsDeleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (part.ParentGroup.IsAttachment)
|
||||||
|
{ // Someone else's HUD, why are we getting these?
|
||||||
|
if (part.ParentGroup.OwnerID != AgentId &&
|
||||||
|
part.ParentGroup.RootPart.Shape.State >= 30)
|
||||||
|
continue;
|
||||||
|
ScenePresence sp;
|
||||||
|
// Owner is not in the sim, don't update it to
|
||||||
|
// anyone
|
||||||
|
if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<SceneObjectGroup> atts = sp.Attachments;
|
||||||
|
bool found = false;
|
||||||
|
foreach (SceneObjectGroup att in atts)
|
||||||
|
{
|
||||||
|
if (att == part.ParentGroup)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's an attachment of a valid avatar, but
|
||||||
|
// doesn't seem to be attached, skip
|
||||||
|
if (!found)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.ParentGroup.IsAttachment && m_disableFacelights)
|
||||||
|
{
|
||||||
|
if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
|
||||||
|
part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
|
||||||
|
{
|
||||||
|
part.Shape.LightEntry = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++updatesThisCall;
|
||||||
|
|
||||||
|
#region UpdateFlags to packet type conversion
|
||||||
|
|
||||||
|
PrimUpdateFlags updateFlags = update.Flags;
|
||||||
|
|
||||||
|
bool canUseCompressed = true;
|
||||||
|
bool canUseImproved = true;
|
||||||
|
|
||||||
|
// Compressed object updates only make sense for LL primitives
|
||||||
|
if (!(update.Entity is SceneObjectPart))
|
||||||
{
|
{
|
||||||
canUseCompressed = false;
|
canUseCompressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
|
if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Text) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Material) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
|
|
||||||
updateFlags.HasFlag(PrimUpdateFlags.Joint))
|
|
||||||
{
|
{
|
||||||
|
canUseCompressed = false;
|
||||||
canUseImproved = false;
|
canUseImproved = false;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
#endregion UpdateFlags to packet type conversion
|
|
||||||
|
|
||||||
#region Block Construction
|
|
||||||
|
|
||||||
// TODO: Remove this once we can build compressed updates
|
|
||||||
canUseCompressed = false;
|
|
||||||
|
|
||||||
if (!canUseImproved && !canUseCompressed)
|
|
||||||
{
|
|
||||||
if (update.Entity is ScenePresence)
|
|
||||||
{
|
{
|
||||||
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
|
if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Joint))
|
||||||
|
{
|
||||||
|
if (update.Entity is ScenePresence)
|
||||||
|
{
|
||||||
|
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Text) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Material) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
|
||||||
|
updateFlags.HasFlag(PrimUpdateFlags.Joint))
|
||||||
|
{
|
||||||
|
canUseImproved = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion UpdateFlags to packet type conversion
|
||||||
|
|
||||||
|
#region Block Construction
|
||||||
|
|
||||||
|
// TODO: Remove this once we can build compressed updates
|
||||||
|
canUseCompressed = false;
|
||||||
|
|
||||||
|
if (!canUseImproved && !canUseCompressed)
|
||||||
|
{
|
||||||
|
if (update.Entity is ScenePresence)
|
||||||
|
{
|
||||||
|
objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
|
||||||
|
// {
|
||||||
|
// SceneObjectPart sop = (SceneObjectPart)update.Entity;
|
||||||
|
// string text = sop.Text;
|
||||||
|
// if (text.IndexOf("\n") >= 0)
|
||||||
|
// text = text.Remove(text.IndexOf("\n"));
|
||||||
|
//
|
||||||
|
// if (m_attachmentsSent.Contains(sop.ParentID))
|
||||||
|
// {
|
||||||
|
//// m_log.DebugFormat(
|
||||||
|
//// "[CLIENT]: Sending full info about attached prim {0} text {1}",
|
||||||
|
//// sop.LocalId, text);
|
||||||
|
//
|
||||||
|
// objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
|
||||||
|
//
|
||||||
|
// m_attachmentsSent.Add(sop.LocalId);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
|
||||||
|
// sop.LocalId, text, sop.ParentID);
|
||||||
|
//
|
||||||
|
// m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!canUseImproved)
|
||||||
|
{
|
||||||
|
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
|
if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
|
||||||
// {
|
// Self updates go into a special list
|
||||||
// SceneObjectPart sop = (SceneObjectPart)update.Entity;
|
terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
||||||
// string text = sop.Text;
|
else
|
||||||
// if (text.IndexOf("\n") >= 0)
|
// Everything else goes here
|
||||||
// text = text.Remove(text.IndexOf("\n"));
|
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
||||||
//
|
|
||||||
// if (m_attachmentsSent.Contains(sop.ParentID))
|
|
||||||
// {
|
|
||||||
//// m_log.DebugFormat(
|
|
||||||
//// "[CLIENT]: Sending full info about attached prim {0} text {1}",
|
|
||||||
//// sop.LocalId, text);
|
|
||||||
//
|
|
||||||
// objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
|
|
||||||
//
|
|
||||||
// m_attachmentsSent.Add(sop.LocalId);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
|
|
||||||
// sop.LocalId, text, sop.ParentID);
|
|
||||||
//
|
|
||||||
// m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (!canUseImproved)
|
|
||||||
{
|
|
||||||
compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
|
|
||||||
// Self updates go into a special list
|
|
||||||
terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
|
||||||
else
|
|
||||||
// Everything else goes here
|
|
||||||
terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Block Construction
|
#endregion Block Construction
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Packet Sending
|
#region Packet Sending
|
||||||
|
@ -3864,26 +3978,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
public void ReprioritizeUpdates()
|
public void ReprioritizeUpdates()
|
||||||
{
|
{
|
||||||
//m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
|
|
||||||
|
|
||||||
lock (m_entityUpdates.SyncRoot)
|
lock (m_entityUpdates.SyncRoot)
|
||||||
m_entityUpdates.Reprioritize(UpdatePriorityHandler);
|
m_entityUpdates.Reprioritize(UpdatePriorityHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpdatePriorityHandler(ref double priority, uint localID)
|
private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
|
||||||
{
|
{
|
||||||
EntityBase entity;
|
if (entity != null)
|
||||||
if (m_scene.Entities.TryGetValue(localID, out entity))
|
|
||||||
{
|
{
|
||||||
priority = m_prioritizer.GetUpdatePriority(this, entity);
|
priority = m_prioritizer.GetUpdatePriority(this, entity);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return priority != double.NaN;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlushPrimUpdates()
|
public void FlushPrimUpdates()
|
||||||
{
|
{
|
||||||
m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
|
m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
|
||||||
|
|
||||||
while (m_entityUpdates.Count > 0)
|
while (m_entityUpdates.Count > 0)
|
||||||
ProcessEntityUpdates(-1);
|
ProcessEntityUpdates(-1);
|
||||||
|
@ -11831,171 +11943,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
OutPacket(pack, ThrottleOutPacketType.Task);
|
OutPacket(pack, ThrottleOutPacketType.Task);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region PriorityQueue
|
|
||||||
public class PriorityQueue
|
|
||||||
{
|
|
||||||
internal delegate bool UpdatePriorityHandler(ref double priority, uint local_id);
|
|
||||||
|
|
||||||
private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
|
|
||||||
private Dictionary<uint, LookupItem> m_lookupTable;
|
|
||||||
private Comparison<double> m_comparison;
|
|
||||||
private object m_syncRoot = new object();
|
|
||||||
|
|
||||||
internal PriorityQueue() :
|
|
||||||
this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<double>.Default) { }
|
|
||||||
internal PriorityQueue(int capacity) :
|
|
||||||
this(capacity, Comparer<double>.Default) { }
|
|
||||||
internal PriorityQueue(IComparer<double> comparer) :
|
|
||||||
this(new Comparison<double>(comparer.Compare)) { }
|
|
||||||
internal PriorityQueue(Comparison<double> comparison) :
|
|
||||||
this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
|
|
||||||
internal PriorityQueue(int capacity, IComparer<double> comparer) :
|
|
||||||
this(capacity, new Comparison<double>(comparer.Compare)) { }
|
|
||||||
internal PriorityQueue(int capacity, Comparison<double> comparison)
|
|
||||||
{
|
|
||||||
m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
|
|
||||||
|
|
||||||
for (int i = 0; i < m_heaps.Length; ++i)
|
|
||||||
m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
|
|
||||||
this.m_comparison = comparison;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object SyncRoot { get { return this.m_syncRoot; } }
|
|
||||||
internal int Count
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < m_heaps.Length; ++i)
|
|
||||||
count = m_heaps[i].Count;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Enqueue(double priority, EntityUpdate value, uint local_id)
|
|
||||||
{
|
|
||||||
LookupItem item;
|
|
||||||
|
|
||||||
if (m_lookupTable.TryGetValue(local_id, out item))
|
|
||||||
{
|
|
||||||
// Combine flags
|
|
||||||
value.Flags |= item.Heap[item.Handle].Value.Flags;
|
|
||||||
|
|
||||||
item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item.Heap = m_heaps[0];
|
|
||||||
item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
|
|
||||||
m_lookupTable.Add(local_id, item);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal EntityUpdate Peek()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < m_heaps.Length; ++i)
|
|
||||||
if (m_heaps[i].Count > 0)
|
|
||||||
return m_heaps[i].Min().Value;
|
|
||||||
throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool TryDequeue(out EntityUpdate value)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < m_heaps.Length; ++i)
|
|
||||||
{
|
|
||||||
if (m_heaps[i].Count > 0)
|
|
||||||
{
|
|
||||||
MinHeapItem item = m_heaps[i].RemoveMin();
|
|
||||||
m_lookupTable.Remove(item.LocalID);
|
|
||||||
value = item.Value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default(EntityUpdate);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Reprioritize(UpdatePriorityHandler handler)
|
|
||||||
{
|
|
||||||
MinHeapItem item;
|
|
||||||
double priority;
|
|
||||||
|
|
||||||
foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
|
|
||||||
{
|
|
||||||
if (lookup.Heap.TryGetValue(lookup.Handle, out item))
|
|
||||||
{
|
|
||||||
priority = item.Priority;
|
|
||||||
if (handler(ref priority, item.LocalID))
|
|
||||||
{
|
|
||||||
if (lookup.Heap.ContainsHandle(lookup.Handle))
|
|
||||||
lookup.Heap[lookup.Handle] =
|
|
||||||
new MinHeapItem(priority, item.Value, item.LocalID, this.m_comparison);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
|
|
||||||
lookup.Heap.Remove(lookup.Handle);
|
|
||||||
this.m_lookupTable.Remove(item.LocalID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region MinHeapItem
|
|
||||||
private struct MinHeapItem : IComparable<MinHeapItem>
|
|
||||||
{
|
|
||||||
private double priority;
|
|
||||||
private EntityUpdate value;
|
|
||||||
private uint local_id;
|
|
||||||
private Comparison<double> comparison;
|
|
||||||
|
|
||||||
internal MinHeapItem(double priority, EntityUpdate value, uint local_id) :
|
|
||||||
this(priority, value, local_id, Comparer<double>.Default) { }
|
|
||||||
internal MinHeapItem(double priority, EntityUpdate value, uint local_id, IComparer<double> comparer) :
|
|
||||||
this(priority, value, local_id, new Comparison<double>(comparer.Compare)) { }
|
|
||||||
internal MinHeapItem(double priority, EntityUpdate value, uint local_id, Comparison<double> comparison)
|
|
||||||
{
|
|
||||||
this.priority = priority;
|
|
||||||
this.value = value;
|
|
||||||
this.local_id = local_id;
|
|
||||||
this.comparison = comparison;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal double Priority { get { return this.priority; } }
|
|
||||||
internal EntityUpdate Value { get { return this.value; } }
|
|
||||||
internal uint LocalID { get { return this.local_id; } }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.Append("[");
|
|
||||||
sb.Append(this.priority.ToString());
|
|
||||||
sb.Append(",");
|
|
||||||
if (this.value != null)
|
|
||||||
sb.Append(this.value.ToString());
|
|
||||||
sb.Append("]");
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(MinHeapItem other)
|
|
||||||
{
|
|
||||||
return this.comparison(this.priority, other.priority);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region LookupItem
|
|
||||||
private struct LookupItem
|
|
||||||
{
|
|
||||||
internal MinHeap<MinHeapItem> Heap;
|
|
||||||
internal IHandle Handle;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct PacketProcessor
|
public struct PacketProcessor
|
||||||
{
|
{
|
||||||
public PacketMethod method;
|
public PacketMethod method;
|
||||||
|
@ -12016,8 +11963,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public static OSD BuildEvent(string eventName, OSD eventBody)
|
public static OSD BuildEvent(string eventName, OSD eventBody)
|
||||||
{
|
{
|
||||||
OSDMap osdEvent = new OSDMap(2);
|
OSDMap osdEvent = new OSDMap(2);
|
||||||
|
|
|
@ -149,7 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>Caches packed throttle information</summary>
|
/// <summary>Caches packed throttle information</summary>
|
||||||
private byte[] m_packedThrottles;
|
private byte[] m_packedThrottles;
|
||||||
|
|
||||||
private int m_defaultRTO = 3000;
|
private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
|
||||||
private int m_maxRTO = 60000;
|
private int m_maxRTO = 60000;
|
||||||
public bool m_deliverPackets = true;
|
public bool m_deliverPackets = true;
|
||||||
|
|
||||||
|
@ -567,7 +567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
|
int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
|
||||||
|
|
||||||
// Clamp the retransmission timeout to manageable values
|
// Clamp the retransmission timeout to manageable values
|
||||||
rto = Utils.Clamp(RTO, m_defaultRTO, m_maxRTO);
|
rto = Utils.Clamp(rto, m_defaultRTO, m_maxRTO);
|
||||||
|
|
||||||
RTO = rto;
|
RTO = rto;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
{
|
||||||
|
public class PriorityQueue
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
|
||||||
|
|
||||||
|
// Heap[0] for self updates
|
||||||
|
// Heap[1..12] for entity updates
|
||||||
|
|
||||||
|
internal const uint m_numberOfQueues = 12;
|
||||||
|
|
||||||
|
private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues];
|
||||||
|
private Dictionary<uint, LookupItem> m_lookupTable;
|
||||||
|
private uint m_nextQueue = 0;
|
||||||
|
private UInt64 m_nextRequest = 0;
|
||||||
|
|
||||||
|
private object m_syncRoot = new object();
|
||||||
|
public object SyncRoot {
|
||||||
|
get { return this.m_syncRoot; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
|
||||||
|
|
||||||
|
internal PriorityQueue(int capacity)
|
||||||
|
{
|
||||||
|
m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
|
||||||
|
|
||||||
|
for (int i = 0; i < m_heaps.Length; ++i)
|
||||||
|
m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < m_heaps.Length; ++i)
|
||||||
|
count += m_heaps[i].Count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Enqueue(uint pqueue, EntityUpdate value)
|
||||||
|
{
|
||||||
|
LookupItem lookup;
|
||||||
|
|
||||||
|
uint localid = value.Entity.LocalId;
|
||||||
|
UInt64 entry = m_nextRequest++;
|
||||||
|
if (m_lookupTable.TryGetValue(localid, out lookup))
|
||||||
|
{
|
||||||
|
entry = lookup.Heap[lookup.Handle].EntryOrder;
|
||||||
|
value.Flags |= lookup.Heap[lookup.Handle].Value.Flags;
|
||||||
|
lookup.Heap.Remove(lookup.Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
|
||||||
|
lookup.Heap = m_heaps[pqueue];
|
||||||
|
lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
|
||||||
|
m_lookupTable[localid] = lookup;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_numberOfQueues; ++i)
|
||||||
|
{
|
||||||
|
// To get the fair queing, we cycle through each of the
|
||||||
|
// queues when finding an element to dequeue, this code
|
||||||
|
// assumes that the distribution of updates in the queues
|
||||||
|
// is polynomial, probably quadractic (eg distance of PI * R^2)
|
||||||
|
uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
|
||||||
|
if (m_heaps[h].Count > 0)
|
||||||
|
{
|
||||||
|
m_nextQueue = (uint)((h + 1) % m_numberOfQueues);
|
||||||
|
|
||||||
|
MinHeapItem item = m_heaps[h].RemoveMin();
|
||||||
|
m_lookupTable.Remove(item.Value.Entity.LocalId);
|
||||||
|
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
|
||||||
|
value = item.Value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timeinqueue = 0;
|
||||||
|
value = default(EntityUpdate);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Reprioritize(UpdatePriorityHandler handler)
|
||||||
|
{
|
||||||
|
MinHeapItem item;
|
||||||
|
foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
|
||||||
|
{
|
||||||
|
if (lookup.Heap.TryGetValue(lookup.Handle, out item))
|
||||||
|
{
|
||||||
|
uint pqueue = item.PriorityQueue;
|
||||||
|
uint localid = item.Value.Entity.LocalId;
|
||||||
|
|
||||||
|
if (handler(ref pqueue, item.Value.Entity))
|
||||||
|
{
|
||||||
|
// unless the priority queue has changed, there is no need to modify
|
||||||
|
// the entry
|
||||||
|
pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
|
||||||
|
if (pqueue != item.PriorityQueue)
|
||||||
|
{
|
||||||
|
lookup.Heap.Remove(lookup.Handle);
|
||||||
|
|
||||||
|
LookupItem litem = lookup;
|
||||||
|
litem.Heap = m_heaps[pqueue];
|
||||||
|
litem.Heap.Add(new MinHeapItem(pqueue, item), ref litem.Handle);
|
||||||
|
m_lookupTable[localid] = litem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID);
|
||||||
|
lookup.Heap.Remove(lookup.Handle);
|
||||||
|
this.m_lookupTable.Remove(localid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string s = "";
|
||||||
|
for (int i = 0; i < m_numberOfQueues; i++)
|
||||||
|
{
|
||||||
|
if (s != "") s += ",";
|
||||||
|
s += m_heaps[i].Count.ToString();
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region MinHeapItem
|
||||||
|
private struct MinHeapItem : IComparable<MinHeapItem>
|
||||||
|
{
|
||||||
|
private EntityUpdate value;
|
||||||
|
internal EntityUpdate Value {
|
||||||
|
get {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint pqueue;
|
||||||
|
internal uint PriorityQueue {
|
||||||
|
get {
|
||||||
|
return this.pqueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Int32 entrytime;
|
||||||
|
internal Int32 EntryTime {
|
||||||
|
get {
|
||||||
|
return this.entrytime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private UInt64 entryorder;
|
||||||
|
internal UInt64 EntryOrder
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return this.entryorder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal MinHeapItem(uint pqueue, MinHeapItem other)
|
||||||
|
{
|
||||||
|
this.entrytime = other.entrytime;
|
||||||
|
this.entryorder = other.entryorder;
|
||||||
|
this.value = other.value;
|
||||||
|
this.pqueue = pqueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value)
|
||||||
|
{
|
||||||
|
this.entrytime = Util.EnvironmentTickCount();
|
||||||
|
this.entryorder = entryorder;
|
||||||
|
this.value = value;
|
||||||
|
this.pqueue = pqueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return String.Format("[{0},{1},{2}]",pqueue,entryorder,value.Entity.LocalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(MinHeapItem other)
|
||||||
|
{
|
||||||
|
// I'm assuming that the root part of an SOG is added to the update queue
|
||||||
|
// before the component parts
|
||||||
|
return Comparer<UInt64>.Default.Compare(this.EntryOrder, other.EntryOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region LookupItem
|
||||||
|
private struct LookupItem
|
||||||
|
{
|
||||||
|
internal MinHeap<MinHeapItem> Heap;
|
||||||
|
internal IHandle Handle;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,8 +29,10 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Security;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
@ -100,8 +102,24 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
|
|
||||||
public HttpRequestModule()
|
public HttpRequestModule()
|
||||||
{
|
{
|
||||||
|
ServicePointManager.ServerCertificateValidationCallback +=ValidateServerCertificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ValidateServerCertificate(
|
||||||
|
object sender,
|
||||||
|
X509Certificate certificate,
|
||||||
|
X509Chain chain,
|
||||||
|
SslPolicyErrors sslPolicyErrors)
|
||||||
|
{
|
||||||
|
HttpWebRequest Request = (HttpWebRequest)sender;
|
||||||
|
|
||||||
|
if (Request.Headers.Get("NoVerifyCert") != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain.Build(new X509Certificate2(certificate));
|
||||||
|
}
|
||||||
#region IHttpRequestModule Members
|
#region IHttpRequestModule Members
|
||||||
|
|
||||||
public UUID MakeHttpRequest(string url, string parameters, string body)
|
public UUID MakeHttpRequest(string url, string parameters, string body)
|
||||||
|
@ -141,8 +159,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
|
case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
|
||||||
|
htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
|
||||||
// TODO implement me
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
* Not sure how important ordering is is here - the next first
|
* Not sure how important ordering is is here - the next first
|
||||||
* one completed in the list is returned, based soley on its list
|
* one completed in the list is returned, based soley on its list
|
||||||
* position, not the order in which the request was started or
|
* position, not the order in which the request was started or
|
||||||
* finsihed. I thought about setting up a queue for this, but
|
* finished. I thought about setting up a queue for this, but
|
||||||
* it will need some refactoring and this works 'enough' right now
|
* it will need some refactoring and this works 'enough' right now
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -237,8 +254,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
|
|
||||||
m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
|
m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
|
||||||
|
|
||||||
m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
|
m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
|
||||||
m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
|
m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
|
||||||
|
|
||||||
m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
|
m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
|
||||||
}
|
}
|
||||||
|
@ -282,7 +299,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
public string HttpMethod = "GET";
|
public string HttpMethod = "GET";
|
||||||
public string HttpMIMEType = "text/plain;charset=utf-8";
|
public string HttpMIMEType = "text/plain;charset=utf-8";
|
||||||
public int HttpTimeout;
|
public int HttpTimeout;
|
||||||
// public bool HttpVerifyCert = true; // not implemented
|
public bool HttpVerifyCert = true;
|
||||||
private Thread httpThread;
|
private Thread httpThread;
|
||||||
|
|
||||||
// Request info
|
// Request info
|
||||||
|
@ -348,6 +365,17 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
Request.Method = HttpMethod;
|
Request.Method = HttpMethod;
|
||||||
Request.ContentType = HttpMIMEType;
|
Request.ContentType = HttpMIMEType;
|
||||||
|
|
||||||
|
if(!HttpVerifyCert)
|
||||||
|
{
|
||||||
|
// We could hijack Connection Group Name to identify
|
||||||
|
// a desired security exception. But at the moment we'll use a dummy header instead.
|
||||||
|
// Request.ConnectionGroupName = "NoVerify";
|
||||||
|
Request.Headers.Add("NoVerifyCert", "true");
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// Request.ConnectionGroupName="Verify";
|
||||||
|
// }
|
||||||
if (proxyurl != null && proxyurl.Length > 0)
|
if (proxyurl != null && proxyurl.Length > 0)
|
||||||
{
|
{
|
||||||
if (proxyexcepts != null && proxyexcepts.Length > 0)
|
if (proxyexcepts != null && proxyexcepts.Length > 0)
|
||||||
|
|
|
@ -223,7 +223,8 @@ namespace OpenSim.Region.Framework
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat(
|
m_log.ErrorFormat(
|
||||||
"[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e);
|
"[MODULES]: Could not load types for plugin DLL {0}. Exception {1} {2}",
|
||||||
|
pluginAssembly.FullName, e.Message, e.StackTrace);
|
||||||
|
|
||||||
// justincc: Right now this is fatal to really get the user's attention
|
// justincc: Right now this is fatal to really get the user's attention
|
||||||
// TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
|
// TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
|
||||||
|
|
|
@ -58,16 +58,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public class Prioritizer
|
public class Prioritizer
|
||||||
{
|
{
|
||||||
// private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is added to the priority of all child prims, to make sure that the root prim update is sent to the
|
|
||||||
/// viewer before child prim updates.
|
|
||||||
/// The adjustment is added to child prims and subtracted from root prims, so the gap ends up
|
|
||||||
/// being double. We do it both ways so that there is a still a priority delta even if the priority is already
|
|
||||||
/// double.MinValue or double.MaxValue.
|
|
||||||
/// </summary>
|
|
||||||
private double m_childPrimAdjustmentFactor = 0.05;
|
|
||||||
|
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
|
||||||
|
@ -76,17 +67,35 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetUpdatePriority(IClientAPI client, ISceneEntity entity)
|
/// <summary>
|
||||||
|
/// Returns the priority queue into which the update should be placed. Updates within a
|
||||||
|
/// queue will be processed in arrival order. There are currently 12 priority queues
|
||||||
|
/// implemented in PriorityQueue class in LLClientView. Queue 0 is generally retained
|
||||||
|
/// for avatar updates. The fair queuing discipline for processing the priority queues
|
||||||
|
/// assumes that the number of entities in each priority queues increases exponentially.
|
||||||
|
/// So for example... if queue 1 contains all updates within 10m of the avatar or camera
|
||||||
|
/// then queue 2 at 20m is about 3X bigger in space & about 3X bigger in total number
|
||||||
|
/// of updates.
|
||||||
|
/// </summary>
|
||||||
|
public uint GetUpdatePriority(IClientAPI client, ISceneEntity entity)
|
||||||
{
|
{
|
||||||
double priority = 0;
|
// If entity is null we have a serious problem
|
||||||
|
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
return 100000;
|
{
|
||||||
|
m_log.WarnFormat("[PRIORITIZER] attempt to prioritize null entity");
|
||||||
|
throw new InvalidOperationException("Prioritization entity not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is an update for our own avatar give it the highest priority
|
||||||
|
if (client.AgentId == entity.UUID)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint priority;
|
||||||
|
|
||||||
switch (m_scene.UpdatePrioritizationScheme)
|
switch (m_scene.UpdatePrioritizationScheme)
|
||||||
{
|
{
|
||||||
case UpdatePrioritizationSchemes.Time:
|
case UpdatePrioritizationSchemes.Time:
|
||||||
priority = GetPriorityByTime();
|
priority = GetPriorityByTime(client, entity);
|
||||||
break;
|
break;
|
||||||
case UpdatePrioritizationSchemes.Distance:
|
case UpdatePrioritizationSchemes.Distance:
|
||||||
priority = GetPriorityByDistance(client, entity);
|
priority = GetPriorityByDistance(client, entity);
|
||||||
|
@ -104,182 +113,119 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
|
throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust priority so that root prims are sent to the viewer first. This is especially important for
|
|
||||||
// attachments acting as huds, since current viewers fail to display hud child prims if their updates
|
|
||||||
// arrive before the root one.
|
|
||||||
if (entity is SceneObjectPart)
|
|
||||||
{
|
|
||||||
SceneObjectPart sop = ((SceneObjectPart)entity);
|
|
||||||
|
|
||||||
if (sop.IsRoot)
|
|
||||||
{
|
|
||||||
if (priority >= double.MinValue + m_childPrimAdjustmentFactor)
|
|
||||||
priority -= m_childPrimAdjustmentFactor;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (priority <= double.MaxValue - m_childPrimAdjustmentFactor)
|
|
||||||
priority += m_childPrimAdjustmentFactor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double GetPriorityByTime()
|
|
||||||
|
private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
|
||||||
{
|
{
|
||||||
return DateTime.UtcNow.ToOADate();
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
|
private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
|
||||||
{
|
{
|
||||||
|
return ComputeDistancePriority(client,entity,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
|
||||||
|
{
|
||||||
|
return ComputeDistancePriority(client,entity,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
|
||||||
|
{
|
||||||
|
if (entity == null) return 0;
|
||||||
|
|
||||||
|
uint pqueue = ComputeDistancePriority(client,entity,true);
|
||||||
|
|
||||||
ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
|
ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
|
||||||
if (presence != null)
|
if (presence != null)
|
||||||
{
|
{
|
||||||
// If this is an update for our own avatar give it the highest priority
|
|
||||||
if (presence == entity)
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
// Use the camera position for local agents and avatar position for remote agents
|
|
||||||
Vector3 presencePos = (presence.IsChildAgent) ?
|
|
||||||
presence.AbsolutePosition :
|
|
||||||
presence.CameraPosition;
|
|
||||||
|
|
||||||
// Use group position for child prims
|
|
||||||
Vector3 entityPos;
|
|
||||||
if (entity is SceneObjectPart)
|
|
||||||
{
|
|
||||||
// Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
|
|
||||||
// before its scheduled update was triggered
|
|
||||||
//entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
|
|
||||||
entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entityPos = entity.AbsolutePosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Vector3.DistanceSquared(presencePos, entityPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return double.NaN;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
|
|
||||||
{
|
|
||||||
if (entity == null) return double.NaN;
|
|
||||||
ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
|
|
||||||
if (presence != null)
|
|
||||||
{
|
|
||||||
// If this is an update for our own avatar give it the highest priority
|
|
||||||
if (presence == entity)
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
// Use group position for child prims
|
|
||||||
Vector3 entityPos = entity.AbsolutePosition;
|
|
||||||
if (entity is SceneObjectPart)
|
|
||||||
{
|
|
||||||
// Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
|
|
||||||
// before its scheduled update was triggered
|
|
||||||
//entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
|
|
||||||
entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entityPos = entity.AbsolutePosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!presence.IsChildAgent)
|
if (!presence.IsChildAgent)
|
||||||
{
|
{
|
||||||
// Root agent. Use distance from camera and a priority decrease for objects behind us
|
if (entity is SceneObjectPart)
|
||||||
Vector3 camPosition = presence.CameraPosition;
|
{
|
||||||
Vector3 camAtAxis = presence.CameraAtAxis;
|
// Non physical prims are lower priority than physical prims
|
||||||
|
PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
|
||||||
|
if (physActor == null || !physActor.IsPhysical)
|
||||||
|
pqueue++;
|
||||||
|
|
||||||
// Distance
|
// Attachments are high priority,
|
||||||
double priority = Vector3.DistanceSquared(camPosition, entityPos);
|
// MIC: shouldn't these already be in the highest priority queue already
|
||||||
|
// since their root position is same as the avatars?
|
||||||
// Plane equation
|
if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
|
||||||
float d = -Vector3.Dot(camPosition, camAtAxis);
|
pqueue = 1;
|
||||||
float p = Vector3.Dot(camAtAxis, entityPos) + d;
|
}
|
||||||
if (p < 0.0f) priority *= 2.0;
|
|
||||||
|
|
||||||
return priority;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Child agent. Use the normal distance method
|
|
||||||
Vector3 presencePos = presence.AbsolutePosition;
|
|
||||||
|
|
||||||
return Vector3.DistanceSquared(presencePos, entityPos);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return double.NaN;
|
return pqueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
|
private uint ComputeDistancePriority(IClientAPI client, ISceneEntity entity, bool useFrontBack)
|
||||||
{
|
{
|
||||||
// If this is an update for our own avatar give it the highest priority
|
// If this is an update for our own avatar give it the highest priority
|
||||||
if (client.AgentId == entity.UUID)
|
if (client.AgentId == entity.UUID)
|
||||||
return 0.0;
|
return 0;
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
return double.NaN;
|
return 0;
|
||||||
|
|
||||||
|
// Get this agent's position
|
||||||
ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
|
ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
|
||||||
if (presence != null)
|
if (presence == null)
|
||||||
{
|
{
|
||||||
// Use group position for child prims
|
m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
|
||||||
Vector3 entityPos;
|
// throw new InvalidOperationException("Prioritization agent not defined");
|
||||||
if (entity is SceneObjectPart)
|
return Int32.MaxValue;
|
||||||
entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
|
|
||||||
else
|
|
||||||
entityPos = entity.AbsolutePosition;
|
|
||||||
|
|
||||||
if (!presence.IsChildAgent)
|
|
||||||
{
|
|
||||||
if (entity is ScenePresence)
|
|
||||||
return 1.0;
|
|
||||||
|
|
||||||
// Root agent. Use distance from camera and a priority decrease for objects behind us
|
|
||||||
Vector3 camPosition = presence.CameraPosition;
|
|
||||||
Vector3 camAtAxis = presence.CameraAtAxis;
|
|
||||||
|
|
||||||
// Distance
|
|
||||||
double priority = Vector3.DistanceSquared(camPosition, entityPos);
|
|
||||||
|
|
||||||
// Plane equation
|
|
||||||
float d = -Vector3.Dot(camPosition, camAtAxis);
|
|
||||||
float p = Vector3.Dot(camAtAxis, entityPos) + d;
|
|
||||||
if (p < 0.0f) priority *= 2.0;
|
|
||||||
|
|
||||||
if (entity is SceneObjectPart)
|
|
||||||
{
|
|
||||||
if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
|
|
||||||
{
|
|
||||||
priority = 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
|
|
||||||
if (physActor == null || !physActor.IsPhysical)
|
|
||||||
priority += 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity)
|
|
||||||
priority +=1;
|
|
||||||
}
|
|
||||||
return priority;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Child agent. Use the normal distance method
|
|
||||||
Vector3 presencePos = presence.AbsolutePosition;
|
|
||||||
|
|
||||||
return Vector3.DistanceSquared(presencePos, entityPos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return double.NaN;
|
// Use group position for child prims, since we are putting child prims in
|
||||||
|
// the same queue with the root of the group, the root prim (which goes into
|
||||||
|
// the queue first) should always be sent first, no need to adjust child prim
|
||||||
|
// priorities
|
||||||
|
Vector3 entityPos = entity.AbsolutePosition;
|
||||||
|
if (entity is SceneObjectPart)
|
||||||
|
{
|
||||||
|
SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup;
|
||||||
|
if (group != null)
|
||||||
|
entityPos = group.AbsolutePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the camera position for local agents and avatar position for remote agents
|
||||||
|
Vector3 presencePos = (presence.IsChildAgent) ?
|
||||||
|
presence.AbsolutePosition :
|
||||||
|
presence.CameraPosition;
|
||||||
|
|
||||||
|
// Compute the distance...
|
||||||
|
double distance = Vector3.Distance(presencePos, entityPos);
|
||||||
|
|
||||||
|
// And convert the distance to a priority queue, this computation gives queues
|
||||||
|
// at 10, 20, 40, 80, 160, 320, 640, and 1280m
|
||||||
|
uint pqueue = 1;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (distance < 10 * Math.Pow(2.0,i))
|
||||||
|
break;
|
||||||
|
pqueue++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a root agent, then determine front & back
|
||||||
|
// Bump up the priority queue (drop the priority) for any objects behind the avatar
|
||||||
|
if (useFrontBack && ! presence.IsChildAgent)
|
||||||
|
{
|
||||||
|
// Root agent, decrease priority for objects behind us
|
||||||
|
Vector3 camPosition = presence.CameraPosition;
|
||||||
|
Vector3 camAtAxis = presence.CameraAtAxis;
|
||||||
|
|
||||||
|
// Plane equation
|
||||||
|
float d = -Vector3.Dot(camPosition, camAtAxis);
|
||||||
|
float p = Vector3.Dot(camAtAxis, entityPos) + d;
|
||||||
|
if (p < 0.0f)
|
||||||
|
pqueue++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pqueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10930,12 +10930,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
UUID rq = UUID.Random();
|
UUID rq = UUID.Random();
|
||||||
|
|
||||||
UUID tid = AsyncCommands.
|
AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
|
||||||
DataserverPlugin.RegisterRequest(m_localID,
|
|
||||||
m_itemID, rq.ToString());
|
|
||||||
|
|
||||||
AsyncCommands.
|
AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
|
||||||
DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
|
|
||||||
|
|
||||||
return rq.ToString();
|
return rq.ToString();
|
||||||
}
|
}
|
||||||
|
@ -10949,12 +10946,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
UUID rq = UUID.Random();
|
UUID rq = UUID.Random();
|
||||||
|
|
||||||
UUID tid = AsyncCommands.
|
AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
|
||||||
DataserverPlugin.RegisterRequest(m_localID,
|
|
||||||
m_itemID, rq.ToString());
|
|
||||||
|
|
||||||
AsyncCommands.
|
AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
|
||||||
DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
|
|
||||||
|
|
||||||
return rq.ToString();
|
return rq.ToString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ namespace OpenSim.Services.Interfaces
|
||||||
/// Get an item, given by its UUID
|
/// Get an item, given by its UUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
/// <returns></returns>
|
/// <returns>null if no item was found, otherwise the found item</returns>
|
||||||
InventoryItemBase GetItem(InventoryItemBase item);
|
InventoryItemBase GetItem(InventoryItemBase item);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,4 +1,22 @@
|
||||||
;; A note on the format of this file
|
;; This is the main configuration file for OpenSimulator. If it's named OpenSim.ini
|
||||||
|
;; then it will be loaded by OpenSimulator. If it's named OpenSim.ini.example then
|
||||||
|
;; you will need to copy it to OpenSim.ini first (if that file does not already exist)
|
||||||
|
;;
|
||||||
|
;; If you are copying, then once you have copied OpenSim.ini.example to OpenSim.ini you will
|
||||||
|
;; need to pick an architecture in the [Architecture] section at the end of this file.
|
||||||
|
;;
|
||||||
|
;; The settings in this file are in the form "<key> = <value>". For example, save_crashes = false
|
||||||
|
;; in the [Startup] section below.
|
||||||
|
;;
|
||||||
|
;; All settings are initially commented out and the default value used, as found in
|
||||||
|
;; OpenSimDefaults.ini. To change a setting, first uncomment it by deleting the initial semicolon (;)
|
||||||
|
;; and then change the value. This will override the value in OpenSimDefaults.ini
|
||||||
|
;;
|
||||||
|
;; If you want to find out what configuration OpenSimulator has finished with once all the configuration
|
||||||
|
;; files are loaded then type "config show" on the region console command line.
|
||||||
|
;;
|
||||||
|
;;
|
||||||
|
;; NOTES FOR DEVELOPERS REGARDING FORMAT OF TIHS FILE
|
||||||
;;
|
;;
|
||||||
;; All leading white space is ignored, but preserved.
|
;; All leading white space is ignored, but preserved.
|
||||||
;;
|
;;
|
||||||
|
@ -8,15 +26,14 @@
|
||||||
;; formatted as:
|
;; formatted as:
|
||||||
;; {option} {depends on} {question to ask} {choices} default value
|
;; {option} {depends on} {question to ask} {choices} default value
|
||||||
;; Any text comments following the declaration, up to the next blank line.
|
;; Any text comments following the declaration, up to the next blank line.
|
||||||
;; will be copied to the generated file.
|
;; will be copied to the generated file (NOTE: generation is not yet implemented)
|
||||||
;; A * in the choices list will allow an empty entry.\
|
;; A * in the choices list will allow an empty entry.
|
||||||
;; An empty question will set the default if the dependencies are
|
;; An empty question will set the default if the dependencies are
|
||||||
;; satisfied.
|
;; satisfied.
|
||||||
;;
|
;;
|
||||||
;; ; denotes a commented out option. Uncomment it to actvate it
|
;; ; denotes a commented out option.
|
||||||
;; and change it to the desired value
|
;; Any options added to OpenSim.ini.example should be initially commented out.
|
||||||
;; Any options added to OpenSim.ini.exmaple must be commented out,
|
|
||||||
;; and their value must represent the default.
|
|
||||||
|
|
||||||
[Startup]
|
[Startup]
|
||||||
;# {save_crashes} {} {Save crashes to disk?} {true false} false
|
;# {save_crashes} {} {Save crashes to disk?} {true false} false
|
||||||
|
@ -35,7 +52,7 @@
|
||||||
|
|
||||||
;; Determine where OpenSimulator looks for the files which tell it
|
;; Determine where OpenSimulator looks for the files which tell it
|
||||||
;; which regions to server
|
;; which regions to server
|
||||||
;; Defaults to "filesystem" if this setting isn't present
|
;; Default is "filesystem"
|
||||||
; region_info_source = "filesystem"
|
; region_info_source = "filesystem"
|
||||||
; region_info_source = "web"
|
; region_info_source = "web"
|
||||||
|
|
||||||
|
@ -131,6 +148,7 @@
|
||||||
;; ZeroMesher is faster but leaves the physics engine to model the mesh
|
;; ZeroMesher is faster but leaves the physics engine to model the mesh
|
||||||
;; using the basic shapes that it supports.
|
;; using the basic shapes that it supports.
|
||||||
;; Usually this is only a box.
|
;; Usually this is only a box.
|
||||||
|
;; Default is Meshmerizer
|
||||||
; meshing = Meshmerizer
|
; meshing = Meshmerizer
|
||||||
; meshing = ZeroMesher
|
; meshing = ZeroMesher
|
||||||
|
|
||||||
|
@ -138,6 +156,7 @@
|
||||||
;; OpenDynamicsEngine is by some distance the most developed physics engine
|
;; OpenDynamicsEngine is by some distance the most developed physics engine
|
||||||
;; basicphysics effectively does not model physics at all, making all
|
;; basicphysics effectively does not model physics at all, making all
|
||||||
;; objects phantom
|
;; objects phantom
|
||||||
|
;; Default is OpenDynamicsEngine
|
||||||
; physics = OpenDynamicsEngine
|
; physics = OpenDynamicsEngine
|
||||||
; physics = basicphysics
|
; physics = basicphysics
|
||||||
; physics = POS
|
; physics = POS
|
||||||
|
@ -154,7 +173,6 @@
|
||||||
;; permission checks (allowing anybody to copy
|
;; permission checks (allowing anybody to copy
|
||||||
;; any item, etc. This may not yet be implemented uniformally.
|
;; any item, etc. This may not yet be implemented uniformally.
|
||||||
;; If set to true, then all permissions checks are carried out
|
;; If set to true, then all permissions checks are carried out
|
||||||
;; Default is false
|
|
||||||
; serverside_object_permissions = false
|
; serverside_object_permissions = false
|
||||||
|
|
||||||
;; This allows users with a UserLevel of 200 or more to assume god
|
;; This allows users with a UserLevel of 200 or more to assume god
|
||||||
|
@ -188,6 +206,7 @@
|
||||||
;; server to send mail through.
|
;; server to send mail through.
|
||||||
; emailmodule = DefaultEmailModule
|
; emailmodule = DefaultEmailModule
|
||||||
|
|
||||||
|
|
||||||
[SMTP]
|
[SMTP]
|
||||||
;; The SMTP server enabled the email module to send email to external
|
;; The SMTP server enabled the email module to send email to external
|
||||||
;; destinations.
|
;; destinations.
|
||||||
|
@ -214,6 +233,7 @@
|
||||||
;# {SMTP_SERVER_PASSWORD} {[Startup]emailmodule:DefaultEmailModule enabled:true} {SMTP server password} {}
|
;# {SMTP_SERVER_PASSWORD} {[Startup]emailmodule:DefaultEmailModule enabled:true} {SMTP server password} {}
|
||||||
; SMTP_SERVER_PASSWORD = ""
|
; SMTP_SERVER_PASSWORD = ""
|
||||||
|
|
||||||
|
|
||||||
[Network]
|
[Network]
|
||||||
;; Configure the remote console user here. This will not actually be used
|
;; Configure the remote console user here. This will not actually be used
|
||||||
;; unless you use -console=rest at startup.
|
;; unless you use -console=rest at startup.
|
||||||
|
@ -247,6 +267,7 @@
|
||||||
;; " (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)"
|
||||||
|
|
||||||
|
|
||||||
[ClientStack.LindenUDP]
|
[ClientStack.LindenUDP]
|
||||||
;; See OpensSimDefaults.ini for the throttle options. You can copy the
|
;; See OpensSimDefaults.ini for the throttle options. You can copy the
|
||||||
;; relevant sections and override them here.
|
;; relevant sections and override them here.
|
||||||
|
@ -263,17 +284,18 @@
|
||||||
;; building's lights to possibly not be rendered.
|
;; building's lights to possibly not be rendered.
|
||||||
; DisableFacelights = "false"
|
; DisableFacelights = "false"
|
||||||
|
|
||||||
|
|
||||||
[Chat]
|
[Chat]
|
||||||
;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10
|
;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10
|
||||||
;; Distance in meters that whispers should travel. Default is 10m
|
;; Distance in meters that whispers should travel.
|
||||||
; whisper_distance = 10
|
; whisper_distance = 10
|
||||||
|
|
||||||
;# {say_distance} {} {Distance at which normal chat is heard, in meters? (SL uses 20 here)} {} 30
|
;# {say_distance} {} {Distance at which normal chat is heard, in meters? (SL uses 20 here)} {} 30
|
||||||
;; Distance in meters that ordinary chat should travel. Default is 30m
|
;; Distance in meters that ordinary chat should travel.
|
||||||
; say_distance = 30
|
; say_distance = 30
|
||||||
|
|
||||||
;# {shout_distance} {Distance at which a shout is heard, in meters?} {} 100
|
;# {shout_distance} {Distance at which a shout is heard, in meters?} {} 100
|
||||||
;; Distance in meters that shouts should travel. Default is 100m
|
;; Distance in meters that shouts should travel.
|
||||||
; shout_distance = 100
|
; shout_distance = 100
|
||||||
|
|
||||||
|
|
||||||
|
@ -337,13 +359,13 @@
|
||||||
;# {create_region_enable_voice} {enabled:true} {Enable voice for newly created regions?} {true false} false
|
;# {create_region_enable_voice} {enabled:true} {Enable voice for newly created regions?} {true false} false
|
||||||
;; set this variable to true if you want the create_region XmlRpc
|
;; set this variable to true if you want the create_region XmlRpc
|
||||||
;; call to unconditionally enable voice on all parcels for a newly
|
;; call to unconditionally enable voice on all parcels for a newly
|
||||||
;; created region [default: false]
|
;; created region
|
||||||
; create_region_enable_voice = false
|
; create_region_enable_voice = false
|
||||||
|
|
||||||
;# {create_region_public} {enabled:true} {Make newly created regions public?} {true false} false
|
;# {create_region_public} {enabled:true} {Make newly created regions public?} {true false} false
|
||||||
;; set this variable to false if you want the create_region XmlRpc
|
;; set this variable to false if you want the create_region XmlRpc
|
||||||
;; call to create all regions as private per default (can be
|
;; call to create all regions as private per default (can be
|
||||||
;; overridden in the XmlRpc call) [default: true]
|
;; overridden in the XmlRpc call)
|
||||||
; create_region_public = false
|
; create_region_public = false
|
||||||
|
|
||||||
;# {enabled_methods} {enabled:true} {List of methods to allow, separated by |} {} all
|
;# {enabled_methods} {enabled:true} {List of methods to allow, separated by |} {} all
|
||||||
|
@ -372,15 +394,16 @@
|
||||||
;; default avatars
|
;; default avatars
|
||||||
; default_appearance = default_appearance.xml
|
; default_appearance = default_appearance.xml
|
||||||
|
|
||||||
|
|
||||||
[Wind]
|
[Wind]
|
||||||
;# {enabled} {} {Enable wind module?} {true false} true
|
;# {enabled} {} {Enable wind module?} {true false} true
|
||||||
;; Enables the wind module. Default is true
|
;; Enables the wind module.
|
||||||
;enabled = true
|
; enabled = true
|
||||||
|
|
||||||
;# {wind_update_rate} {enabled:true} {Wind update rate in frames?} {} 150
|
;# {wind_update_rate} {enabled:true} {Wind update rate in frames?} {} 150
|
||||||
;; How often should wind be updated, as a function of world frames.
|
;; How often should wind be updated, as a function of world frames.
|
||||||
;; Approximately 50 frames a second
|
;; Approximately 50 frames a second
|
||||||
wind_update_rate = 150
|
; wind_update_rate = 150
|
||||||
|
|
||||||
;; The Default Wind Plugin to load
|
;; The Default Wind Plugin to load
|
||||||
; wind_plugin = SimpleRandomWind
|
; wind_plugin = SimpleRandomWind
|
||||||
|
@ -396,9 +419,10 @@
|
||||||
|
|
||||||
;# {strength} {enabled:true wind_plugin:SimpleRandomWind} {Wind strength?} {} 1.0
|
;# {strength} {enabled:true wind_plugin:SimpleRandomWind} {Wind strength?} {} 1.0
|
||||||
;; This setting is specific to the SimpleRandomWind plugin
|
;; This setting is specific to the SimpleRandomWind plugin
|
||||||
;; Adjusts wind strength. 0.0 = no wind, 1.0 = normal wind. Default is 1.0
|
;; Adjusts wind strength. 0.0 = no wind, 1.0 = normal wind.
|
||||||
; strength = 1.0
|
; strength = 1.0
|
||||||
|
|
||||||
|
|
||||||
[LightShare]
|
[LightShare]
|
||||||
;# {enable_windlight} {} {Enable LightShare technology?} {true false} false
|
;# {enable_windlight} {} {Enable LightShare technology?} {true false} false
|
||||||
;; This enables the transmission of Windlight scenes to supporting clients,
|
;; This enables the transmission of Windlight scenes to supporting clients,
|
||||||
|
@ -406,7 +430,8 @@
|
||||||
;; It has no ill effect on viewers which do not support server-side
|
;; It has no ill effect on viewers which do not support server-side
|
||||||
;; windlight settings.
|
;; windlight settings.
|
||||||
;; Currently we only have support for MySQL databases.
|
;; Currently we only have support for MySQL databases.
|
||||||
; enable_windlight = false;
|
; enable_windlight = false
|
||||||
|
|
||||||
|
|
||||||
[DataSnapshot]
|
[DataSnapshot]
|
||||||
;# {index_sims} {} {Enable data snapshotting (search)?} {true false} false
|
;# {index_sims} {} {Enable data snapshotting (search)?} {true false} false
|
||||||
|
@ -417,7 +442,6 @@
|
||||||
;; and you can ignore the rest of these search-related configs.
|
;; and you can ignore the rest of these search-related configs.
|
||||||
; index_sims = false
|
; index_sims = false
|
||||||
|
|
||||||
|
|
||||||
;# {data_exposure} {index_sims:true} {How much data should be exposed?} {minimum all} minimum
|
;# {data_exposure} {index_sims:true} {How much data should be exposed?} {minimum all} minimum
|
||||||
;; The variable data_exposure controls what the regions expose:
|
;; The variable data_exposure controls what the regions expose:
|
||||||
;; minimum: exposes only things explicitly marked for search
|
;; minimum: exposes only things explicitly marked for search
|
||||||
|
@ -462,6 +486,7 @@
|
||||||
;; Money Unit fee to create groups
|
;; Money Unit fee to create groups
|
||||||
; PriceGroupCreate = 0
|
; PriceGroupCreate = 0
|
||||||
|
|
||||||
|
|
||||||
[XEngine]
|
[XEngine]
|
||||||
;# {Enabled} {} {Enable the XEngine scripting engine?} {true false} true
|
;# {Enabled} {} {Enable the XEngine scripting engine?} {true false} true
|
||||||
;; Enable this engine in this OpenSim instance
|
;; Enable this engine in this OpenSim instance
|
||||||
|
@ -556,9 +581,9 @@
|
||||||
;; Default is ./bin/ScriptEngines
|
;; Default is ./bin/ScriptEngines
|
||||||
; ScriptEnginesPath = "ScriptEngines"
|
; ScriptEnginesPath = "ScriptEngines"
|
||||||
|
|
||||||
|
|
||||||
[MRM]
|
[MRM]
|
||||||
;; Enables the Mini Region Modules Script Engine.
|
;; Enables the Mini Region Modules Script Engine.
|
||||||
;; default is false
|
|
||||||
; Enabled = false
|
; Enabled = false
|
||||||
|
|
||||||
;; Runs MRM in a Security Sandbox
|
;; Runs MRM in a Security Sandbox
|
||||||
|
@ -580,6 +605,7 @@
|
||||||
;; May represent a security risk if you disable this.
|
;; May represent a security risk if you disable this.
|
||||||
; OwnerOnly = true
|
; OwnerOnly = true
|
||||||
|
|
||||||
|
|
||||||
[FreeSwitchVoice]
|
[FreeSwitchVoice]
|
||||||
;; In order for this to work you need a functioning FreeSWITCH PBX set up.
|
;; In order for this to work you need a functioning FreeSWITCH PBX set up.
|
||||||
;; Configuration details at http://opensimulator.org/wiki/Freeswitch_Module
|
;; Configuration details at http://opensimulator.org/wiki/Freeswitch_Module
|
||||||
|
@ -593,6 +619,7 @@
|
||||||
;; If using a remote module, specify the server URL
|
;; If using a remote module, specify the server URL
|
||||||
; FreeswitchServiceURL = http://my.grid.server:8003/fsapi
|
; FreeswitchServiceURL = http://my.grid.server:8003/fsapi
|
||||||
|
|
||||||
|
|
||||||
[FreeswitchService]
|
[FreeswitchService]
|
||||||
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
;; !!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
;; !!!!!!STANDALONE ONLY!!!!!!
|
;; !!!!!!STANDALONE ONLY!!!!!!
|
||||||
|
@ -611,6 +638,7 @@
|
||||||
; UserName = "freeswitch"
|
; UserName = "freeswitch"
|
||||||
; Password = "password"
|
; Password = "password"
|
||||||
|
|
||||||
|
|
||||||
[Groups]
|
[Groups]
|
||||||
;# {Enabled} {} {Enable groups?} {true false} false
|
;# {Enabled} {} {Enable groups?} {true false} false
|
||||||
;; Enables the groups module
|
;; Enables the groups module
|
||||||
|
@ -634,7 +662,7 @@
|
||||||
;# {ServicesConnectorModule} {Module:GroupsModule} {Service connector to use for groups} {XmlRpcGroupsServicesConnector SimianGroupsServicesConnector} XmlRpcGroupsServicesConnector
|
;# {ServicesConnectorModule} {Module:GroupsModule} {Service connector to use for groups} {XmlRpcGroupsServicesConnector SimianGroupsServicesConnector} XmlRpcGroupsServicesConnector
|
||||||
;; Service connectors to the Groups Service as used in the GroupsModule. Select one depending on
|
;; Service connectors to the Groups Service as used in the GroupsModule. Select one depending on
|
||||||
;; whether you're using a Flotsam XmlRpc backend or a SimianGrid backend
|
;; whether you're using a Flotsam XmlRpc backend or a SimianGrid backend
|
||||||
; ServicesConnectorModule = SimianGroupsServicesConnector
|
; ServicesConnectorModule = XmlRpcGroupsServicesConnector
|
||||||
|
|
||||||
;# {GroupsServerURI} {Module:GroupsModule} {Groups Server URI} {}
|
;# {GroupsServerURI} {Module:GroupsModule} {Groups Server URI} {}
|
||||||
;; URI for the groups services
|
;; URI for the groups services
|
||||||
|
@ -654,6 +682,7 @@
|
||||||
; XmlRpcServiceReadKey = 1234
|
; XmlRpcServiceReadKey = 1234
|
||||||
; XmlRpcServiceWriteKey = 1234
|
; XmlRpcServiceWriteKey = 1234
|
||||||
|
|
||||||
|
|
||||||
[InterestManagement]
|
[InterestManagement]
|
||||||
;# {UpdatePrioritizationScheme} {} {Update prioritization scheme?} {BestAvatarResponsiveness Time Distance SimpleAngularDistance FrontBack} BestAvatarResponsiveness
|
;# {UpdatePrioritizationScheme} {} {Update prioritization scheme?} {BestAvatarResponsiveness Time Distance SimpleAngularDistance FrontBack} BestAvatarResponsiveness
|
||||||
;; This section controls how state updates are prioritized for each client
|
;; This section controls how state updates are prioritized for each client
|
||||||
|
@ -661,24 +690,28 @@
|
||||||
;; SimpleAngularDistance, FrontBack
|
;; SimpleAngularDistance, FrontBack
|
||||||
; UpdatePrioritizationScheme = BestAvatarResponsiveness
|
; UpdatePrioritizationScheme = BestAvatarResponsiveness
|
||||||
|
|
||||||
|
|
||||||
[MediaOnAPrim]
|
[MediaOnAPrim]
|
||||||
;# {Enabled} {} {Enable Media-on-a-Prim (MOAP)} {true false} true
|
;# {Enabled} {} {Enable Media-on-a-Prim (MOAP)} {true false} true
|
||||||
;; Enable media on a prim facilities
|
;; Enable media on a prim facilities
|
||||||
; Enabled = true;
|
; Enabled = true;
|
||||||
|
|
||||||
|
|
||||||
[Architecture]
|
[Architecture]
|
||||||
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini config-include/SimianGrid.ini config-include/HyperSimianGrid.ini} config-include/Standalone.ini
|
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini config-include/SimianGrid.ini config-include/HyperSimianGrid.ini} config-include/Standalone.ini
|
||||||
;; Choose one of these architecture includes:
|
;; Uncomment one of the following includes as required. For instance, to create a standalone OpenSim,
|
||||||
;; Include-Architecture = "config-include/Standalone.ini"
|
;; uncomment Include-Architecture = "config-include/Standalone.ini"
|
||||||
;; Include-Architecture = "config-include/StandaloneHypergrid.ini"
|
;;
|
||||||
;; Include-Architecture = "config-include/Grid.ini"
|
;; Then you will need to copy and edit the corresponding *Common.example file in config-include/
|
||||||
;; Include-Architecture = "config-include/GridHypergrid.ini"
|
;; that the referenced .ini file goes on to include.
|
||||||
;; Include-Architecture = "config-include/SimianGrid.ini"
|
;;
|
||||||
;; Include-Architecture = "config-include/HyperSimianGrid.ini"
|
;; For instance, if you chose "config-include/Standalone.ini" then you will need to copy
|
||||||
|
;; "config-include/StandaloneCommon.ini.example" to "config-include/StandaloneCommon.ini" before
|
||||||
|
;; editing it to set the database and backend services that OpenSim will use.
|
||||||
|
;;
|
||||||
; Include-Architecture = "config-include/Standalone.ini"
|
; Include-Architecture = "config-include/Standalone.ini"
|
||||||
|
; Include-Architecture = "config-include/StandaloneHypergrid.ini"
|
||||||
;; Then choose
|
; Include-Architecture = "config-include/Grid.ini"
|
||||||
;; config-include/StandaloneCommon.ini.example (if you're in standlone) OR
|
; Include-Architecture = "config-include/GridHypergrid.ini"
|
||||||
;; config-include/GridCommon.ini.example (if you're connected to a grid)
|
; Include-Architecture = "config-include/SimianGrid.ini"
|
||||||
;; Copy to your own .ini there (without .example extension) and edit it
|
; Include-Architecture = "config-include/HyperSimianGrid.ini"
|
||||||
;; to customize your data
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
; This file contains defaults for various settings in OpenSimulator. These can be overriden
|
||||||
|
; by changing the same setting in OpenSim.ini (once OpenSim.ini.example has been copied to OpenSim.ini).
|
||||||
|
|
||||||
|
|
||||||
[Startup]
|
[Startup]
|
||||||
; Set this to true if you want to log crashes to disk
|
; Set this to true if you want to log crashes to disk
|
||||||
; this can be useful when submitting bug reports.
|
; this can be useful when submitting bug reports.
|
||||||
|
@ -287,6 +291,7 @@
|
||||||
;SMTP_SERVER_LOGIN=foo
|
;SMTP_SERVER_LOGIN=foo
|
||||||
;SMTP_SERVER_PASSWORD=bar
|
;SMTP_SERVER_PASSWORD=bar
|
||||||
|
|
||||||
|
|
||||||
[Network]
|
[Network]
|
||||||
ConsoleUser = "Test"
|
ConsoleUser = "Test"
|
||||||
ConsolePass = "secret"
|
ConsolePass = "secret"
|
||||||
|
@ -317,6 +322,7 @@
|
||||||
; " (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)"
|
||||||
|
|
||||||
|
|
||||||
[XMLRPC]
|
[XMLRPC]
|
||||||
; ##
|
; ##
|
||||||
; ## Scripting XMLRPC mapper
|
; ## Scripting XMLRPC mapper
|
||||||
|
@ -330,6 +336,7 @@
|
||||||
;XmlRpcRouterModule = "XmlRpcRouterModule"
|
;XmlRpcRouterModule = "XmlRpcRouterModule"
|
||||||
;XmlRpcPort = 20800
|
;XmlRpcPort = 20800
|
||||||
|
|
||||||
|
|
||||||
[ClientStack.LindenUDP]
|
[ClientStack.LindenUDP]
|
||||||
; Set this to true to process incoming packets asynchronously. Networking is
|
; Set this to true to process incoming packets asynchronously. Networking is
|
||||||
; already separated from packet handling with a queue, so this will only
|
; already separated from packet handling with a queue, so this will only
|
||||||
|
@ -422,6 +429,7 @@
|
||||||
;
|
;
|
||||||
;DisableFacelights = "false"
|
;DisableFacelights = "false"
|
||||||
|
|
||||||
|
|
||||||
[Chat]
|
[Chat]
|
||||||
; Controls whether the chat module is enabled. Default is true.
|
; Controls whether the chat module is enabled. Default is true.
|
||||||
enabled = true;
|
enabled = true;
|
||||||
|
@ -680,6 +688,7 @@
|
||||||
; path to default appearance XML file that specifies the look of the default avatars
|
; path to default appearance XML file that specifies the look of the default avatars
|
||||||
;default_appearance = default_appearance.xml
|
;default_appearance = default_appearance.xml
|
||||||
|
|
||||||
|
|
||||||
[RestPlugins]
|
[RestPlugins]
|
||||||
; Change this to true to enable REST Plugins. This must be true if you wish to use
|
; Change this to true to enable REST Plugins. This must be true if you wish to use
|
||||||
; REST Region or REST Asset and Inventory Plugins
|
; REST Region or REST Asset and Inventory Plugins
|
||||||
|
@ -706,11 +715,10 @@
|
||||||
flush-on-error = true
|
flush-on-error = true
|
||||||
|
|
||||||
|
|
||||||
; Uncomment the following for IRC bridge
|
; IRC bridge is experimental, so if it breaks... keep both parts... yada yada
|
||||||
; experimental, so if it breaks... keep both parts... yada yada
|
|
||||||
; also, not good error detection when it fails
|
; also, not good error detection when it fails
|
||||||
;[IRC]
|
[IRC]
|
||||||
;enabled = true ; you need to set this otherwise it won't connect
|
enabled = false; you need to set this to true otherwise it won't connect
|
||||||
;server = name.of.irc.server.on.the.net
|
;server = name.of.irc.server.on.the.net
|
||||||
;; user password - only use this if the server requires one
|
;; user password - only use this if the server requires one
|
||||||
;password = mypass
|
;password = mypass
|
||||||
|
@ -767,14 +775,14 @@
|
||||||
;exclude_list=User 1,User 2,User 3
|
;exclude_list=User 1,User 2,User 3
|
||||||
|
|
||||||
|
|
||||||
;[CMS]
|
[CMS]
|
||||||
;enabled = true
|
enabled = false
|
||||||
;channel = 345
|
;channel = 345
|
||||||
|
|
||||||
|
|
||||||
; Uncomment the following to control the progression of daytime
|
; The following settings control the progression of daytime
|
||||||
; in the Sim. The defaults are what is shown below
|
; in the Sim. The defaults are the same as the commented out settings
|
||||||
;[Sun]
|
[Sun]
|
||||||
; number of wall clock hours for an opensim day. 24.0 would mean realtime
|
; number of wall clock hours for an opensim day. 24.0 would mean realtime
|
||||||
;day_length = 4
|
;day_length = 4
|
||||||
; Year length in days
|
; Year length in days
|
||||||
|
@ -821,12 +829,13 @@
|
||||||
; default is 1000
|
; default is 1000
|
||||||
cloud_update_rate = 1000
|
cloud_update_rate = 1000
|
||||||
|
|
||||||
[LightShare]
|
|
||||||
|
|
||||||
|
[LightShare]
|
||||||
; This enables the transmission of Windlight scenes to supporting clients, such as the Meta7 viewer.
|
; This enables the transmission of Windlight scenes to supporting clients, such as the Meta7 viewer.
|
||||||
; It has no ill effect on viewers which do not support server-side windlight settings.
|
; It has no ill effect on viewers which do not support server-side windlight settings.
|
||||||
; Currently we only have support for MySQL databases.
|
; Currently we only have support for MySQL databases.
|
||||||
enable_windlight = false;
|
enable_windlight = false
|
||||||
|
|
||||||
|
|
||||||
[Trees]
|
[Trees]
|
||||||
; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying
|
; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying
|
||||||
|
@ -838,7 +847,6 @@
|
||||||
|
|
||||||
|
|
||||||
[VectorRender]
|
[VectorRender]
|
||||||
|
|
||||||
; the font to use for rendering text (default: Arial)
|
; the font to use for rendering text (default: Arial)
|
||||||
; font_name = "Arial"
|
; font_name = "Arial"
|
||||||
|
|
||||||
|
@ -1032,6 +1040,7 @@
|
||||||
;; Path to script assemblies
|
;; Path to script assemblies
|
||||||
; ScriptEnginesPath = "ScriptEngines"
|
; ScriptEnginesPath = "ScriptEngines"
|
||||||
|
|
||||||
|
|
||||||
[OpenGridProtocol]
|
[OpenGridProtocol]
|
||||||
;These are the settings for the Open Grid Protocol.. the Agent Domain, Region Domain, you know..
|
;These are the settings for the Open Grid Protocol.. the Agent Domain, Region Domain, you know..
|
||||||
;On/true or Off/false
|
;On/true or Off/false
|
||||||
|
@ -1240,11 +1249,11 @@
|
||||||
ChildReprioritizationDistance = 20.0
|
ChildReprioritizationDistance = 20.0
|
||||||
|
|
||||||
|
|
||||||
[WebStats]
|
|
||||||
; View region statistics via a web page
|
; View region statistics via a web page
|
||||||
; See http://opensimulator.org/wiki/FAQ#Region_Statistics_on_a_Web_Page
|
; See http://opensimulator.org/wiki/FAQ#Region_Statistics_on_a_Web_Page
|
||||||
; Use a web browser and type in the "Login URI" + "/SStats/"
|
; Use a web browser and type in the "Login URI" + "/SStats/"
|
||||||
; For example- http://127.0.0.1:9000/SStats/
|
; For example- http://127.0.0.1:9000/SStats/
|
||||||
|
[WebStats]
|
||||||
; enabled=false
|
; enabled=false
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
bin/libode.dylib
BIN
bin/libode.dylib
Binary file not shown.
Loading…
Reference in New Issue