Merge branch 'careminster-presence-refactor' of ssh://3dhosting.de/var/git/careminster into careminster-presence-refactor

avinationmerge
Melanie 2011-02-11 23:53:52 +01:00
commit 413f0c6848
13 changed files with 605 additions and 405 deletions

View File

@ -669,10 +669,6 @@ namespace OpenSim.Data.SQLite
} }
} }
/// <summary>
///
/// </summary>
/// <param name="globalID"></param>
public void RemoveLandObject(UUID globalID) public void RemoveLandObject(UUID globalID)
{ {
lock (ds) lock (ds)
@ -698,7 +694,6 @@ namespace OpenSim.Data.SQLite
if (landRow != null) if (landRow != null)
{ {
landRow.Delete(); landRow.Delete();
land.Rows.Remove(landRow);
} }
List<DataRow> rowsToDelete = new List<DataRow>(); List<DataRow> rowsToDelete = new List<DataRow>();
foreach (DataRow rowToCheck in landaccesslist.Rows) foreach (DataRow rowToCheck in landaccesslist.Rows)
@ -709,7 +704,6 @@ namespace OpenSim.Data.SQLite
for (int iter = 0; iter < rowsToDelete.Count; iter++) for (int iter = 0; iter < rowsToDelete.Count; iter++)
{ {
rowsToDelete[iter].Delete(); rowsToDelete[iter].Delete();
landaccesslist.Rows.Remove(rowsToDelete[iter]);
} }
} }
Commit(); Commit();

View File

@ -1030,11 +1030,12 @@ namespace OpenSim
delegate(Scene scene) delegate(Scene scene)
{ {
MainConsole.Instance.Output(String.Format( MainConsole.Instance.Output(String.Format(
"Region Name: {0}, Region XLoc: {1}, Region YLoc: {2}, Region Port: {3}", "Region Name: {0}, Region XLoc: {1}, Region YLoc: {2}, Region Port: {3}, Estate Name: {4}",
scene.RegionInfo.RegionName, scene.RegionInfo.RegionName,
scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocX,
scene.RegionInfo.RegionLocY, scene.RegionInfo.RegionLocY,
scene.RegionInfo.InternalEndPoint.Port)); scene.RegionInfo.InternalEndPoint.Port,
scene.RegionInfo.EstateSettings.EstateName));
}); });
break; break;

View File

@ -27,6 +27,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@ -639,10 +640,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
object[] array = new object[] { buffer, packet }; object[] array = new object[] { buffer, packet };
if (m_asyncPacketHandling) Util.FireAndForget(HandleUseCircuitCode, array);
Util.FireAndForget(HandleUseCircuitCode, array);
else
HandleUseCircuitCode(array);
return; return;
} }
@ -859,10 +857,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Begin the process of adding the client to the simulator // Begin the process of adding the client to the simulator
AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint); AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);
// Acknowledge the UseCircuitCode packet // Send ack
SendAckImmediate(remoteEndPoint, packet.Header.Sequence); SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
// buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
} }
@ -926,25 +924,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) protected virtual void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
{ {
// Create the LLUDPClient // In priciple there shouldn't be more than one thread here, ever.
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); // But in case that happens, we need to synchronize this piece of code
IClientAPI existingClient; // because it's too important
lock (this)
if (!m_scene.TryGetClient(agentID, out existingClient))
{ {
// Create the LLClientView IClientAPI existingClient;
LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
client.OnLogout += LogoutHandler;
client.DisableFacelights = m_disableFacelights; if (!m_scene.TryGetClient(agentID, out existingClient))
{
// Create the LLUDPClient
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
// Create the LLClientView
LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
client.OnLogout += LogoutHandler;
// Start the IClientAPI client.DisableFacelights = m_disableFacelights;
client.Start();
} // Start the IClientAPI
else client.Start();
{
m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}", }
udpClient.AgentID, remoteEndPoint, circuitCode); else
{
m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}",
existingClient.AgentId, remoteEndPoint, circuitCode);
}
} }
} }
@ -1055,6 +1060,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion Update Timers #endregion Update Timers
// Use this for emergency monitoring -- bug hunting
//if (m_scene.EmergencyMonitoring)
// clientPacketHandler = MonitoredClientOutgoingPacketHandler;
//else
// clientPacketHandler = ClientOutgoingPacketHandler;
// Handle outgoing packets, resends, acknowledgements, and pings for each // Handle outgoing packets, resends, acknowledgements, and pings for each
// client. m_packetSent will be set to true if a packet is sent // client. m_packetSent will be set to true if a packet is sent
m_scene.ForEachClient(clientPacketHandler); m_scene.ForEachClient(clientPacketHandler);
@ -1070,6 +1081,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
} }
} }
Watchdog.RemoveThread(); Watchdog.RemoveThread();
@ -1107,6 +1119,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
} }
#region Emergency Monitoring
// Alternative packet handler fuull of instrumentation
// Handy for hunting bugs
private Stopwatch watch1 = new Stopwatch();
private Stopwatch watch2 = new Stopwatch();
private float avgProcessingTicks = 0;
private float avgResendUnackedTicks = 0;
private float avgSendAcksTicks = 0;
private float avgSendPingTicks = 0;
private float avgDequeueTicks = 0;
private long nticks = 0;
private long nticksUnack = 0;
private long nticksAck = 0;
private long nticksPing = 0;
private int npacksSent = 0;
private int npackNotSent = 0;
private void MonitoredClientOutgoingPacketHandler(IClientAPI client)
{
nticks++;
watch1.Start();
try
{
if (client is LLClientView)
{
LLUDPClient udpClient = ((LLClientView)client).UDPClient;
if (udpClient.IsConnected)
{
if (m_resendUnacked)
{
nticksUnack++;
watch2.Start();
ResendUnacked(udpClient);
watch2.Stop();
avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
watch2.Reset();
}
if (m_sendAcks)
{
nticksAck++;
watch2.Start();
SendAcks(udpClient);
watch2.Stop();
avgSendAcksTicks = (nticksAck - 1) / (float)nticksAck * avgSendAcksTicks + (watch2.ElapsedTicks / (float)nticksAck);
watch2.Reset();
}
if (m_sendPing)
{
nticksPing++;
watch2.Start();
SendPing(udpClient);
watch2.Stop();
avgSendPingTicks = (nticksPing - 1) / (float)nticksPing * avgSendPingTicks + (watch2.ElapsedTicks / (float)nticksPing);
watch2.Reset();
}
watch2.Start();
// Dequeue any outgoing packets that are within the throttle limits
if (udpClient.DequeueOutgoing())
{
m_packetSent = true;
npacksSent++;
}
else
npackNotSent++;
watch2.Stop();
avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks);
watch2.Reset();
}
else
m_log.WarnFormat("[LLUDPSERVER]: Client is not connected");
}
}
catch (Exception ex)
{
m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name +
" threw an exception: " + ex.Message, ex);
}
watch1.Stop();
avgProcessingTicks = (nticks - 1) / (float)nticks * avgProcessingTicks + (watch1.ElapsedTicks / (float)nticks);
watch1.Reset();
// reuse this -- it's every ~100ms
if (m_scene.EmergencyMonitoring && nticks % 100 == 0)
{
m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})",
avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent);
npackNotSent = npacksSent = 0;
}
}
#endregion
private void ProcessInPacket(object state) private void ProcessInPacket(object state)
{ {
IncomingPacket incomingPacket = (IncomingPacket)state; IncomingPacket incomingPacket = (IncomingPacket)state;

View File

@ -141,46 +141,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private void ProcessQueues() private void ProcessQueues()
{ {
// Process all the pending adds // Process all the pending adds
OutgoingPacket pendingAdd; OutgoingPacket pendingAdd;
if (m_pendingAdds != null) while (m_pendingAdds.TryDequeue(out pendingAdd))
{ if (pendingAdd != null)
while (m_pendingAdds.TryDequeue(out pendingAdd)) m_packets[pendingAdd.SequenceNumber] = pendingAdd;
{
if (pendingAdd != null && m_packets != null)
{
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
}
}
}
// Process all the pending removes, including updating statistics and round-trip times // Process all the pending removes, including updating statistics and round-trip times
PendingAck pendingRemove; PendingAck pendingRemove;
OutgoingPacket ackedPacket; OutgoingPacket ackedPacket;
if (m_pendingRemoves != null) while (m_pendingRemoves.TryDequeue(out pendingRemove))
{ {
while (m_pendingRemoves.TryDequeue(out pendingRemove)) if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
{ {
if (m_pendingRemoves != null && m_packets != null) if (ackedPacket != null)
{ {
if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) m_packets.Remove(pendingRemove.SequenceNumber);
// Update stats
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
if (!pendingRemove.FromResend)
{ {
m_packets.Remove(pendingRemove.SequenceNumber); // Calculate the round-trip time for this packet and its ACK
int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
// Update stats if (rtt > 0)
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); ackedPacket.Client.UpdateRoundTrip(rtt);
if (!pendingRemove.FromResend)
{
// Calculate the round-trip time for this packet and its ACK
int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
if (rtt > 0)
ackedPacket.Client.UpdateRoundTrip(rtt);
}
} }
} }
} }
} }
} }
} }
} }

View File

@ -139,7 +139,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
if (scene != null) if (scene != null)
{ {
UserAccount account = scene.UserAccountService.GetUserAccount(UUID.Zero, userID); UserAccount account = scene.UserAccountService.GetUserAccount(UUID.Zero, new UUID(userID));
isAuthorized = IsAuthorizedForRegion(userID, account.FirstName, account.LastName, isAuthorized = IsAuthorizedForRegion(userID, account.FirstName, account.LastName,
account.Email, scene.RegionInfo.RegionName, regionID, out message); account.Email, scene.RegionInfo.RegionName, regionID, out message);
} }

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security;
using log4net;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.World.Estate
{
public class EstateManagementCommands
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected EstateManagementModule m_module;
public EstateManagementCommands(EstateManagementModule module)
{
m_module = module;
}
public void Initialise()
{
m_module.Scene.AddCommand(this, "set terrain texture",
"set terrain texture <number> <uuid> [<x>] [<y>]",
"Sets the terrain <number> to <uuid>, if <x> or <y> are specified, it will only " +
"set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" +
" that coordinate.",
consoleSetTerrainTexture);
m_module.Scene.AddCommand(this, "set terrain heights",
"set terrain heights <corner> <min> <max> [<x>] [<y>]",
"Sets the terrain texture heights on corner #<corner> to <min>/<max>, if <x> or <y> are specified, it will only " +
"set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" +
" that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3.",
consoleSetTerrainHeights);
}
protected void consoleSetTerrainTexture(string module, string[] args)
{
string num = args[3];
string uuid = args[4];
int x = (args.Length > 5 ? int.Parse(args[5]) : -1);
int y = (args.Length > 6 ? int.Parse(args[6]) : -1);
if (x == -1 || m_module.Scene.RegionInfo.RegionLocX == x)
{
if (y == -1 || m_module.Scene.RegionInfo.RegionLocY == y)
{
int corner = int.Parse(num);
UUID texture = UUID.Parse(uuid);
m_log.Debug("[ESTATEMODULE]: Setting terrain textures for " + m_module.Scene.RegionInfo.RegionName +
string.Format(" (C#{0} = {1})", corner, texture));
switch (corner)
{
case 0:
m_module.Scene.RegionInfo.RegionSettings.TerrainTexture1 = texture;
break;
case 1:
m_module.Scene.RegionInfo.RegionSettings.TerrainTexture2 = texture;
break;
case 2:
m_module.Scene.RegionInfo.RegionSettings.TerrainTexture3 = texture;
break;
case 3:
m_module.Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture;
break;
}
m_module.Scene.RegionInfo.RegionSettings.Save();
m_module.TriggerRegionInfoChange();
m_module.sendRegionInfoPacketToAll();
}
}
}
protected void consoleSetTerrainHeights(string module, string[] args)
{
string num = args[3];
string min = args[4];
string max = args[5];
int x = (args.Length > 6 ? int.Parse(args[6]) : -1);
int y = (args.Length > 7 ? int.Parse(args[7]) : -1);
if (x == -1 || m_module.Scene.RegionInfo.RegionLocX == x)
{
if (y == -1 || m_module.Scene.RegionInfo.RegionLocY == y)
{
int corner = int.Parse(num);
float lowValue = float.Parse(min, Culture.NumberFormatInfo);
float highValue = float.Parse(max, Culture.NumberFormatInfo);
m_log.Debug("[ESTATEMODULE]: Setting terrain heights " + m_module.Scene.RegionInfo.RegionName +
string.Format(" (C{0}, {1}-{2}", corner, lowValue, highValue));
switch (corner)
{
case 0:
m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue;
break;
case 1:
m_module.Scene.RegionInfo.RegionSettings.Elevation1NW = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2NW = highValue;
break;
case 2:
m_module.Scene.RegionInfo.RegionSettings.Elevation1SE = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2SE = highValue;
break;
case 3:
m_module.Scene.RegionInfo.RegionSettings.Elevation1NE = lowValue;
m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
break;
}
m_module.Scene.RegionInfo.RegionSettings.Save();
m_module.TriggerRegionInfoChange();
m_module.sendRegionHandshakeToAll();
}
}
}
}
}

View File

@ -764,10 +764,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
if (!responseMap.ContainsKey(itemtype.ToString())) // remote sim doesnt have the stated region handle if (!responseMap.ContainsKey(itemtype.ToString())) // remote sim doesnt have the stated region handle
{ {
if (!m_blacklistedregions.ContainsKey(regionhandle)) m_log.DebugFormat("[WORLD MAP]: Remote sim does not have the stated region. Blacklisting.");
lock (m_blacklistedregions)
{ {
m_log.DebugFormat("[WORLD MAP]: Remote sim does not have the stated region. Blacklisting."); if (!m_blacklistedregions.ContainsKey(regionhandle))
m_blacklistedregions.Add(regionhandle, Environment.TickCount); m_blacklistedregions.Add(regionhandle, Environment.TickCount);
} }
} }

View File

@ -64,6 +64,8 @@ namespace OpenSim.Region.Framework.Scenes
#region Fields #region Fields
public bool EmergencyMonitoring = false;
public SynchronizeSceneHandler SynchronizeScene; public SynchronizeSceneHandler SynchronizeScene;
public SimStatsReporter StatsReporter; public SimStatsReporter StatsReporter;
public List<Border> NorthBorders = new List<Border>(); public List<Border> NorthBorders = new List<Border>();

View File

@ -95,7 +95,15 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
"Show throttle settings for each client and for the server overall", "Show throttle settings for each client and for the server overall",
"Without the 'full' option, only root agents are shown." "Without the 'full' option, only root agents are shown."
+ " With the 'full' option child agents are also shown.", + " With the 'full' option child agents are also shown.",
ShowThrottlesReport); ShowThrottlesReport);
scene.AddCommand(
this, "emergency-monitoring",
"Go on/off emergency monitoring mode",
"Go on/off emergency monitoring mode",
"Go on/off emergency monitoring mode",
EmergencyMonitoring);
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
@ -120,7 +128,25 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
{ {
MainConsole.Instance.Output(GetThrottlesReport(cmd)); MainConsole.Instance.Output(GetThrottlesReport(cmd));
} }
protected void EmergencyMonitoring(string module, string[] cmd)
{
bool mode = true;
if (cmd.Length == 1 || (cmd.Length > 1 && cmd[1] == "on"))
{
mode = true;
MainConsole.Instance.Output("Emergency Monitoring ON");
}
else
{
mode = false;
MainConsole.Instance.Output("Emergency Monitoring OFF");
}
foreach (Scene s in m_scenes.Values)
s.EmergencyMonitoring = mode;
}
protected string GetColumnEntry(string entry, int maxLength, int columnPadding) protected string GetColumnEntry(string entry, int maxLength, int columnPadding)
{ {
return string.Format( return string.Format(
@ -335,7 +361,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
ThrottleRates throttleRates = udpServer.ThrottleRates; ThrottleRates throttleRates = udpServer.ThrottleRates;
report.AppendFormat( report.AppendFormat(
"{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}", "{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}",
"n/a", (throttleRates.Total * 8) / 1000,
(throttleRates.ResendLimit * 8) / 1000, (throttleRates.ResendLimit * 8) / 1000,
(throttleRates.LandLimit * 8) / 1000, (throttleRates.LandLimit * 8) / 1000,
(throttleRates.WindLimit * 8) / 1000, (throttleRates.WindLimit * 8) / 1000,

View File

@ -205,6 +205,11 @@ namespace OpenSim.Server.Handlers.Simulation
// We're behind a proxy // We're behind a proxy
Hashtable headers = (Hashtable)request["headers"]; Hashtable headers = (Hashtable)request["headers"];
//// DEBUG
//foreach (object o in headers.Keys)
// m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString()));
string xff = "X-Forwarded-For"; string xff = "X-Forwarded-For";
if (headers.ContainsKey(xff.ToLower())) if (headers.ContainsKey(xff.ToLower()))
xff = xff.ToLower(); xff = xff.ToLower();

View File

@ -306,6 +306,9 @@
[ODEPhysicsSettings] [ODEPhysicsSettings]
;# {mesh_sculpted_prim} {[Startup]physics:OpenDynamicsEngine} {Mesh sculpties so they collide as they look?} {true false} true ;# {mesh_sculpted_prim} {[Startup]physics:OpenDynamicsEngine} {Mesh sculpties so they collide as they look?} {true false} true
;; Do we want to mesh sculpted prim to collide like they look? ;; Do we want to mesh sculpted prim to collide like they look?
;; If you are seeing sculpt texture decode problems
;; (messages such as "Decoded image with unhandled number of components: 0 shortly followed by a physcs exception")
;; then you might want to try setting this to false.
; mesh_sculpted_prim = true ; mesh_sculpted_prim = true
;# {use_NINJA_physics_joints} {[Startup]physics:OpenDynamicsEngine} {Use jointed (NINJA) physics?} {true false} false ;# {use_NINJA_physics_joints} {[Startup]physics:OpenDynamicsEngine} {Use jointed (NINJA) physics?} {true false} false

Binary file not shown.