httptests
UbitUmarov 2017-07-20 11:30:12 +01:00
commit fe6ad384e4
60 changed files with 2493 additions and 41860 deletions

View File

@ -566,7 +566,7 @@ namespace OpenSim.Framework.Capabilities
endPos = FindEnd(llsd, 1); endPos = FindEnd(llsd, 1);
if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float, if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float,
Utils.EnUsCulture.NumberFormat, out value)) Culture.NumberFormatInfo, out value))
return value; return value;
else else
throw new LLSDParseException("Failed to parse double value type"); throw new LLSDParseException("Failed to parse double value type");

View File

@ -88,6 +88,7 @@ namespace OpenSim.Region.Framework.Interfaces
bool IsForcefulBansAllowed(); bool IsForcefulBansAllowed();
void UpdateLandObject(int localID, LandData data); void UpdateLandObject(int localID, LandData data);
void SendParcelsOverlay(IClientAPI client);
void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient); void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient);
void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel); void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel);
void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel); void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel);

View File

@ -64,25 +64,25 @@ namespace OpenSim.Framework
private void XWfloat(string name, float f) private void XWfloat(string name, float f)
{ {
writer.WriteElementString(name, f.ToString(Utils.EnUsCulture)); writer.WriteElementString(name, f.ToString(Culture.FormatProvider));
} }
private void XWVector(string name, Vector3 vec) private void XWVector(string name, Vector3 vec)
{ {
writer.WriteStartElement(name); writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture)); writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture)); writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture)); writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
writer.WriteEndElement(); writer.WriteEndElement();
} }
private void XWVector4(string name, Vector4 quat) private void XWVector4(string name, Vector4 quat)
{ {
writer.WriteStartElement(name); writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture)); writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture)); writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture)); writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture)); writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
writer.WriteEndElement(); writer.WriteEndElement();
} }

View File

@ -216,6 +216,27 @@ namespace OpenSim.Framework
return false; return false;
} }
public bool TryOrderedDequeue(out EntityUpdate value, out Int32 timeinqueue)
{
// If there is anything in imediate queues, return it first no
// matter what else. Breaks fairness. But very useful.
for (int iq = 0; iq < NumberOfQueues; iq++)
{
if (m_heaps[iq].Count > 0)
{
MinHeapItem item = m_heaps[iq].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;
}
/// <summary> /// <summary>
/// Reapply the prioritization function to each of the updates currently /// Reapply the prioritization function to each of the updates currently
/// stored in the priority queues. /// stored in the priority queues.

View File

@ -156,12 +156,14 @@ namespace OpenSim.Framework
public static readonly int MAX_THREADPOOL_LEVEL = 3; public static readonly int MAX_THREADPOOL_LEVEL = 3;
public static double TimeStampClockPeriodMS; public static double TimeStampClockPeriodMS;
public static double TimeStampClockPeriod;
static Util() static Util()
{ {
LogThreadPool = 0; LogThreadPool = 0;
LogOverloads = true; LogOverloads = true;
TimeStampClockPeriodMS = 1000.0D / (double)Stopwatch.Frequency; TimeStampClockPeriod = 1.0D/ (double)Stopwatch.Frequency;
TimeStampClockPeriodMS = 1e3 * TimeStampClockPeriod;
m_log.InfoFormat("[UTIL] TimeStamp clock with period of {0}ms", Math.Round(TimeStampClockPeriodMS,6,MidpointRounding.AwayFromZero)); m_log.InfoFormat("[UTIL] TimeStamp clock with period of {0}ms", Math.Round(TimeStampClockPeriodMS,6,MidpointRounding.AwayFromZero));
} }
@ -2221,9 +2223,9 @@ namespace OpenSim.Framework
// might have gotten an oversized array even after the string trim // might have gotten an oversized array even after the string trim
byte[] data = UTF8.GetBytes(str); byte[] data = UTF8.GetBytes(str);
if (data.Length > 256) if (data.Length > 255) //play safe
{ {
int cut = 255; int cut = 254;
if((data[cut] & 0x80 ) != 0 ) if((data[cut] & 0x80 ) != 0 )
{ {
while(cut > 0 && (data[cut] & 0xc0) != 0xc0) while(cut > 0 && (data[cut] & 0xc0) != 0xc0)
@ -2967,9 +2969,9 @@ namespace OpenSim.Framework
/// <returns></returns> /// <returns></returns>
public static Int32 EnvironmentTickCount() public static Int32 EnvironmentTickCount()
{ {
double now = GetTimeStampMS(); return Environment.TickCount & EnvironmentTickCountMask;
return (int)now;
} }
const Int32 EnvironmentTickCountMask = 0x3fffffff; const Int32 EnvironmentTickCountMask = 0x3fffffff;
/// <summary> /// <summary>
@ -2994,8 +2996,7 @@ namespace OpenSim.Framework
/// <returns>subtraction of passed prevValue from current Environment.TickCount</returns> /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
public static Int32 EnvironmentTickCountSubtract(Int32 prevValue) public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
{ {
double now = GetTimeStampMS(); return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue);
return EnvironmentTickCountSubtract((int)now, prevValue);
} }
// Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
@ -3017,6 +3018,11 @@ namespace OpenSim.Framework
// returns a timestamp in ms as double // returns a timestamp in ms as double
// using the time resolution avaiable to StopWatch // using the time resolution avaiable to StopWatch
public static double GetTimeStamp()
{
return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriod;
}
public static double GetTimeStampMS() public static double GetTimeStampMS()
{ {
return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriodMS; return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriodMS;

View File

@ -220,7 +220,7 @@ namespace OpenSim.Region.ClientStack.Linden
PollServiceMeshEventArgs args; PollServiceMeshEventArgs args;
if (m_pollservices.TryGetValue(user, out args)) if (m_pollservices.TryGetValue(user, out args))
{ {
args.UpdateThrottle(imagethrottle, p); args.UpdateThrottle(imagethrottle);
} }
} }
@ -238,14 +238,13 @@ namespace OpenSim.Region.ClientStack.Linden
base(null, uri, null, null, null, null, pId, int.MaxValue) base(null, uri, null, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); m_throttler = new MeshCapsDataThrottler(100000);
// x is request id, y is userid // x is request id, y is userid
HasEvents = (x, y) => HasEvents = (x, y) =>
{ {
lock (responses) lock (responses)
{ {
bool ret = m_throttler.hasEvents(x, responses); bool ret = m_throttler.hasEvents(x, responses);
m_throttler.ProcessTime();
return ret; return ret;
} }
@ -271,8 +270,8 @@ namespace OpenSim.Region.ClientStack.Linden
} }
finally finally
{ {
m_throttler.ProcessTime();
responses.Remove(x); responses.Remove(x);
m_throttler.PassTime();
} }
} }
}; };
@ -285,6 +284,7 @@ namespace OpenSim.Region.ClientStack.Linden
reqinfo.request = y; reqinfo.request = y;
m_queue.Enqueue(reqinfo); m_queue.Enqueue(reqinfo);
m_throttler.PassTime();
}; };
// this should never happen except possible on shutdown // this should never happen except possible on shutdown
@ -364,12 +364,15 @@ namespace OpenSim.Region.ClientStack.Linden
}; };
} }
m_throttler.ProcessTime(); m_throttler.PassTime();
} }
internal void UpdateThrottle(int pimagethrottle, ScenePresence p) internal void UpdateThrottle(int pthrottle)
{ {
m_throttler.UpdateThrottle(pimagethrottle, p); int tmp = 2 * pthrottle;
if(tmp < 10000)
tmp = 10000;
m_throttler.ThrottleBytes = tmp;
} }
} }
@ -423,24 +426,15 @@ namespace OpenSim.Region.ClientStack.Linden
internal sealed class MeshCapsDataThrottler internal sealed class MeshCapsDataThrottler
{ {
private double lastTimeElapsed = 0;
private double BytesSent = 0;
private volatile int currenttime = 0; public MeshCapsDataThrottler(int pBytes)
private volatile int lastTimeElapsed = 0;
private volatile int BytesSent = 0;
private int CapSetThrottle = 0;
private readonly Scene m_scene;
private ThrottleOutPacketType Throttle;
private readonly UUID User;
public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
{ {
if(pBytes < 10000)
pBytes = 10000;
ThrottleBytes = pBytes; ThrottleBytes = pBytes;
if(ThrottleBytes < 10000) lastTimeElapsed = Util.GetTimeStampMS();
ThrottleBytes = 10000;
lastTimeElapsed = Util.EnvironmentTickCount();
Throttle = ThrottleOutPacketType.Asset;
m_scene = pScene;
User = puser;
} }
public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses) public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
@ -470,46 +464,22 @@ namespace OpenSim.Region.ClientStack.Linden
return haskey; return haskey;
} }
public void ProcessTime() public void PassTime()
{ {
PassTime(); double currenttime = Util.GetTimeStampMS();
} double timeElapsed = currenttime - lastTimeElapsed;
if(timeElapsed < 50.0)
private void PassTime() return;
{ int add = (int)(ThrottleBytes * timeElapsed * 0.001);
currenttime = Util.EnvironmentTickCount(); if (add >= 1000)
int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
if (timeElapsed >= 100)
{ {
lastTimeElapsed = currenttime; lastTimeElapsed = currenttime;
BytesSent -= (ThrottleBytes * timeElapsed / 1000); BytesSent -= add;
if (BytesSent < 0) BytesSent = 0; if (BytesSent < 0) BytesSent = 0;
} }
} }
private void AlterThrottle(int setting, ScenePresence p) public int ThrottleBytes;
{
p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting);
}
public int ThrottleBytes
{
get { return CapSetThrottle; }
set
{
if (value > 10000)
CapSetThrottle = value;
else
CapSetThrottle = 10000;
}
}
internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
{
// Client set throttle !
CapSetThrottle = 2 * pimagethrottle;
ProcessTime();
}
} }
} }
} }

View File

@ -221,7 +221,7 @@ namespace OpenSim.Region.ClientStack.Linden
private HashSet<UUID> dropedResponses = new HashSet<UUID>(); private HashSet<UUID> dropedResponses = new HashSet<UUID>();
private Scene m_scene; private Scene m_scene;
private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); private CapsDataThrottler m_throttler = new CapsDataThrottler(100000);
public PollServiceTextureEventArgs(UUID pId, Scene scene) : public PollServiceTextureEventArgs(UUID pId, Scene scene) :
base(null, "", null, null, null, null, pId, int.MaxValue) base(null, "", null, null, null, null, pId, int.MaxValue)
{ {
@ -232,7 +232,6 @@ namespace OpenSim.Region.ClientStack.Linden
lock (responses) lock (responses)
{ {
bool ret = m_throttler.hasEvents(x, responses); bool ret = m_throttler.hasEvents(x, responses);
m_throttler.ProcessTime();
return ret; return ret;
} }
@ -258,6 +257,7 @@ namespace OpenSim.Region.ClientStack.Linden
finally finally
{ {
responses.Remove(x); responses.Remove(x);
m_throttler.PassTime();
} }
} }
}; };
@ -282,6 +282,7 @@ namespace OpenSim.Region.ClientStack.Linden
} }
} }
m_queue.Enqueue(reqinfo); m_queue.Enqueue(reqinfo);
m_throttler.PassTime();
}; };
// this should never happen except possible on shutdown // this should never happen except possible on shutdown
@ -381,14 +382,15 @@ namespace OpenSim.Region.ClientStack.Linden
response = response response = response
}; };
} }
m_throttler.ProcessTime(); m_throttler.PassTime();
} }
internal void UpdateThrottle(int pimagethrottle) internal void UpdateThrottle(int pimagethrottle)
{ {
m_throttler.ThrottleBytes = 2 * pimagethrottle; int tmp = 2 * pimagethrottle;
if(m_throttler.ThrottleBytes < 10000) if(tmp < 10000)
m_throttler.ThrottleBytes = 10000; tmp = 10000;
m_throttler.ThrottleBytes = tmp;
} }
} }
@ -456,15 +458,14 @@ namespace OpenSim.Region.ClientStack.Linden
internal sealed class CapsDataThrottler internal sealed class CapsDataThrottler
{ {
private volatile int currenttime = 0; private double lastTimeElapsed = 0;
private volatile int lastTimeElapsed = 0;
private volatile int BytesSent = 0; private volatile int BytesSent = 0;
public CapsDataThrottler(int pBytes, int max, int min) public CapsDataThrottler(int pBytes)
{ {
if(pBytes < 10000)
pBytes = 10000;
ThrottleBytes = pBytes; ThrottleBytes = pBytes;
if(ThrottleBytes < 10000) lastTimeElapsed = Util.GetTimeStampMS();
ThrottleBytes = 10000;
lastTimeElapsed = Util.EnvironmentTickCount();
} }
public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses) public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
{ {
@ -497,20 +498,17 @@ namespace OpenSim.Region.ClientStack.Linden
return haskey; return haskey;
} }
public void ProcessTime() public void PassTime()
{ {
PassTime(); double currenttime = Util.GetTimeStampMS();
} double timeElapsed = currenttime - lastTimeElapsed;
if(timeElapsed < 50.0)
private void PassTime() return;
{ int add = (int)(ThrottleBytes * timeElapsed * 0.001);
currenttime = Util.EnvironmentTickCount(); if (add >= 1000)
int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
//processTimeBasedActions(responses);
if (timeElapsed >= 100)
{ {
lastTimeElapsed = currenttime; lastTimeElapsed = currenttime;
BytesSent -= (ThrottleBytes * timeElapsed / 1000); BytesSent -= add;
if (BytesSent < 0) BytesSent = 0; if (BytesSent < 0) BytesSent = 0;
} }
} }

View File

@ -4137,6 +4137,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Vector3 mypos = Vector3.Zero; Vector3 mypos = Vector3.Zero;
ScenePresence mysp = (ScenePresence)SceneAgent; ScenePresence mysp = (ScenePresence)SceneAgent;
bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
// we should have a presence // we should have a presence
if(mysp == null) if(mysp == null)
return; return;
@ -4151,8 +4152,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
while (maxUpdatesBytes > 0) while (maxUpdatesBytes > 0)
{ {
lock (m_entityUpdates.SyncRoot) lock (m_entityUpdates.SyncRoot)
{
if(orderedDequeue)
{
if (!m_entityUpdates.TryOrderedDequeue(out update, out timeinqueue))
break;
}
else
{
if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) if (!m_entityUpdates.TryDequeue(out update, out timeinqueue))
break; break;
}
}
PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
@ -4850,6 +4861,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates = // OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
// new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>(); // new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
EntityUpdate iupdate; EntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later Int32 timeinqueue; // this is just debugging code & can be dropped later
@ -4857,8 +4869,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
while (maxUpdateBytes > 0) while (maxUpdateBytes > 0)
{ {
lock (m_entityProps.SyncRoot) lock (m_entityProps.SyncRoot)
{
if(orderedDequeue)
{
if (!m_entityProps.TryOrderedDequeue(out iupdate, out timeinqueue))
break;
}
else
{
if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
break; break;
}
}
ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
if (update.SendFamilyProps) if (update.SendFamilyProps)
@ -5526,6 +5548,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion #endregion
#region Helper Methods #region Helper Methods
private void ClampVectorForUint(ref Vector3 v, float max)
{
float a,b;
a = Math.Abs(v.X);
b = Math.Abs(v.Y);
if(b > a)
a = b;
b= Math.Abs(v.Z);
if(b > a)
a = b;
if (a > max)
{
a = max / a;
v.X *= a;
v.Y *= a;
v.Z *= a;
}
}
protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture) protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture)
{ {
@ -5616,11 +5658,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
pos += 12; pos += 12;
// Velocity // Velocity
ClampVectorForUint(ref velocity, 128f);
Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2;
Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2;
Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2;
// Acceleration // Acceleration
ClampVectorForUint(ref acceleration, 64f);
Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2;
Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2;
Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2;
@ -5632,6 +5676,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2;
// Angular Velocity // Angular Velocity
ClampVectorForUint(ref angularVelocity, 64f);
Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2;
Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
@ -5753,7 +5798,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//update.JointPivot = Vector3.Zero; //update.JointPivot = Vector3.Zero;
//update.JointType = 0; //update.JointType = 0;
update.Material = part.Material; update.Material = part.Material;
update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
/* /*
if (data.ParentGroup.IsAttachment) if (data.ParentGroup.IsAttachment)
{ {
@ -5832,8 +5876,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.TextureAnim = part.TextureAnimation ?? Utils.EmptyBytes; update.TextureAnim = part.TextureAnimation ?? Utils.EmptyBytes;
update.TextureEntry = part.Shape.TextureEntry ?? Utils.EmptyBytes; update.TextureEntry = part.Shape.TextureEntry ?? Utils.EmptyBytes;
update.Scale = part.Shape.Scale; update.Scale = part.Shape.Scale;
update.Text = Util.StringToBytes256(part.Text); update.Text = Util.StringToBytes(part.Text, 255);
update.MediaURL = Util.StringToBytes256(part.MediaUrl); update.MediaURL = Util.StringToBytes(part.MediaUrl, 255);
#region PrimFlags #region PrimFlags
@ -6234,20 +6278,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name='x'></param> /// <param name='x'></param>
private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
{ {
float vdelta = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); if(Math.Abs(x.CameraCenter.X - m_thisAgentUpdateArgs.CameraCenter.X) > VDELTA ||
if((vdelta > VDELTA)) Math.Abs(x.CameraCenter.Y - m_thisAgentUpdateArgs.CameraCenter.Y) > VDELTA ||
return true; Math.Abs(x.CameraCenter.Z - m_thisAgentUpdateArgs.CameraCenter.Z) > VDELTA ||
vdelta = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); Math.Abs(x.CameraAtAxis.X - m_thisAgentUpdateArgs.CameraAtAxis.X) > VDELTA ||
if((vdelta > VDELTA)) Math.Abs(x.CameraAtAxis.Y - m_thisAgentUpdateArgs.CameraAtAxis.Y) > VDELTA ||
return true; // Math.Abs(x.CameraAtAxis.Z - m_thisAgentUpdateArgs.CameraAtAxis.Z) > VDELTA ||
vdelta = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); Math.Abs(x.CameraLeftAxis.X - m_thisAgentUpdateArgs.CameraLeftAxis.X) > VDELTA ||
if((vdelta > VDELTA)) Math.Abs(x.CameraLeftAxis.Y - m_thisAgentUpdateArgs.CameraLeftAxis.Y) > VDELTA ||
return true; // Math.Abs(x.CameraLeftAxis.Z - m_thisAgentUpdateArgs.CameraLeftAxis.Z) > VDELTA ||
vdelta = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); Math.Abs(x.CameraUpAxis.X - m_thisAgentUpdateArgs.CameraUpAxis.X) > VDELTA ||
if((vdelta > VDELTA)) Math.Abs(x.CameraUpAxis.Y - m_thisAgentUpdateArgs.CameraUpAxis.Y) > VDELTA
// Math.Abs(x.CameraLeftAxis.Z - m_thisAgentUpdateArgs.CameraLeftAxis.Z) > VDELTA ||
)
return true; return true;
return false; return false;

View File

@ -221,7 +221,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// Don't chase down link asset items as they actually point to their target item IDs rather than an asset // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
{
int curErrorCntr = m_assetGatherer.ErrorCount;
int possible = m_assetGatherer.possibleNotAssetCount;
m_assetGatherer.AddForInspection(inventoryItem.AssetID); m_assetGatherer.AddForInspection(inventoryItem.AssetID);
m_assetGatherer.GatherAll();
curErrorCntr = m_assetGatherer.ErrorCount - curErrorCntr;
possible = m_assetGatherer.possibleNotAssetCount - possible;
if(curErrorCntr > 0 || possible > 0)
{
string spath;
int indx = path.IndexOf("__");
if(indx > 0)
spath = path.Substring(0,indx);
else
spath = path;
if(curErrorCntr > 0)
{
m_log.ErrorFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references to missing or damaged assets",
inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, curErrorCntr);
if(possible > 0)
m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item also contains {0} references that may be to missing or damaged assets or not a problem", possible);
}
else if(possible > 0)
{
m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references that may be to missing or damaged assets or not a problem", inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, possible);
}
}
}
} }
/// <summary> /// <summary>
@ -381,6 +410,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath);
Exception e = new InventoryArchiverException(errorMessage); Exception e = new InventoryArchiverException(errorMessage);
m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0); m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0);
if(m_saveStream != null && m_saveStream.CanWrite)
m_saveStream.Close();
throw e; throw e;
} }
@ -420,17 +451,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
{ {
m_assetGatherer.GatherAll(); m_assetGatherer.GatherAll();
m_log.DebugFormat( int errors = m_assetGatherer.FailedUUIDs.Count;
"[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count);
AssetsRequest ar m_log.DebugFormat(
= new AssetsRequest( "[INVENTORY ARCHIVER]: The items to save reference {0} possible assets", m_assetGatherer.GatheredUuids.Count + errors);
if(errors > 0)
m_log.DebugFormat("[INVENTORY ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
AssetsRequest ar = new AssetsRequest(
new AssetsArchiver(m_archiveWriter), new AssetsArchiver(m_archiveWriter),
m_assetGatherer.GatheredUuids, m_scene.AssetService, m_assetGatherer.GatheredUuids, m_assetGatherer.FailedUUIDs.Count,
m_scene.AssetService,
m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
options, ReceivedAllAssets); options, ReceivedAllAssets);
ar.Execute();
WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name));
} }
else else
{ {

View File

@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// { // {
try try
{ {
new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream).Execute(options, UserAccountService); InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream);
iarReq.Execute(options, UserAccountService);
} }
catch (EntryPointNotFoundException e) catch (EntryPointNotFoundException e)
{ {
@ -261,7 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// { // {
try try
{ {
new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath).Execute(options, UserAccountService); InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath);
iarReq.Execute(options, UserAccountService);
} }
catch (EntryPointNotFoundException e) catch (EntryPointNotFoundException e)
{ {

View File

@ -412,7 +412,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
Dictionary<UUID, Quaternion> originalRotations = new Dictionary<UUID, Quaternion>(); Dictionary<UUID, Quaternion> originalRotations = new Dictionary<UUID, Quaternion>();
// this possible is not needed if keyframes are saved // this possible is not needed if keyframes are saved
Dictionary<UUID, KeyframeMotion> originalKeyframes = new Dictionary<UUID, KeyframeMotion>(); // Dictionary<UUID, KeyframeMotion> originalKeyframes = new Dictionary<UUID, KeyframeMotion>();
foreach (SceneObjectGroup objectGroup in objlist) foreach (SceneObjectGroup objectGroup in objlist)
{ {
@ -423,8 +423,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
objectGroup.RootPart.SetForce(Vector3.Zero); objectGroup.RootPart.SetForce(Vector3.Zero);
objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false); objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion; // originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion;
objectGroup.RootPart.KeyframeMotion = null; // objectGroup.RootPart.KeyframeMotion = null;
Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition; Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition;
originalPositions[objectGroup.UUID] = inventoryStoredPosition; originalPositions[objectGroup.UUID] = inventoryStoredPosition;
@ -476,7 +476,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
{ {
objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
objectGroup.RootPart.RotationOffset = originalRotations[objectGroup.UUID]; objectGroup.RootPart.RotationOffset = originalRotations[objectGroup.UUID];
objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID]; // objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID];
if (objectGroup.RootPart.KeyframeMotion != null) if (objectGroup.RootPart.KeyframeMotion != null)
objectGroup.RootPart.KeyframeMotion.Resume(); objectGroup.RootPart.KeyframeMotion.Resume();
} }
@ -989,11 +989,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// one full update during the attachment // one full update during the attachment
// process causes some clients to fail to display the // process causes some clients to fail to display the
// attachment properly. // attachment properly.
m_Scene.AddNewSceneObject(group, true, false);
if (!attachment) if (!attachment)
{ {
group.AbsolutePosition = pos + veclist[i]; group.AbsolutePosition = pos + veclist[i];
m_Scene.AddNewSceneObject(group, true, false);
// Fire on_rez // Fire on_rez
group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
@ -1001,6 +1001,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
group.ScheduleGroupForFullUpdate(); group.ScheduleGroupForFullUpdate();
} }
else
m_Scene.AddNewSceneObject(group, true, false);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", // "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",

View File

@ -135,20 +135,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
m_reuseableDynamicTextures.Store( m_reuseableDynamicTextures.Store(
GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
} }
} updater.newTextureID = newTextureID;
} }
if (updater.UpdateTimer == 0)
{
lock (Updaters) lock (Updaters)
{ {
if (!Updaters.ContainsKey(updater.UpdaterID)) if (Updaters.ContainsKey(updater.UpdaterID))
{
Updaters.Remove(updater.UpdaterID); Updaters.Remove(updater.UpdaterID);
} }
} }
} }
}
/// <summary> /// <summary>
/// Determines whether the texture is reuseable based on its data size. /// Determines whether the texture is reuseable based on its data size.
@ -172,21 +168,20 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
} }
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
string extraParams, int updateTimer) string extraParams)
{ {
return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, false, 255);
} }
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) string extraParams, bool SetBlending, byte AlphaValue)
{ {
return AddDynamicTextureURL(simID, primID, contentType, url, return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, SetBlending,
extraParams, updateTimer, SetBlending, (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
(int)(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
} }
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
string extraParams, int updateTimer, bool SetBlending, string extraParams, bool SetBlending,
int disp, byte AlphaValue, int face) int disp, byte AlphaValue, int face)
{ {
if (RenderPlugins.ContainsKey(contentType)) if (RenderPlugins.ContainsKey(contentType))
@ -196,7 +191,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.PrimID = primID; updater.PrimID = primID;
updater.ContentType = contentType; updater.ContentType = contentType;
updater.Url = url; updater.Url = url;
updater.UpdateTimer = updateTimer;
updater.UpdaterID = UUID.Random(); updater.UpdaterID = UUID.Random();
updater.Params = extraParams; updater.Params = extraParams;
updater.BlendWithOldTexture = SetBlending; updater.BlendWithOldTexture = SetBlending;
@ -213,26 +207,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
} }
RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
return updater.UpdaterID; return updater.newTextureID;
} }
return UUID.Zero; return UUID.Zero;
} }
public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
string extraParams, int updateTimer) string extraParams)
{ {
return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); return AddDynamicTextureData(simID, primID, contentType, data, extraParams, false,
(DISP_TEMP|DISP_EXPIRE), 255, ALL_SIDES);
} }
public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) string extraParams, bool SetBlending, byte AlphaValue)
{ {
return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, SetBlending, return AddDynamicTextureData(simID, primID, contentType, data, extraParams, SetBlending,
(int) (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
} }
public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) string extraParams, bool SetBlending, int disp, byte AlphaValue, int face)
{ {
if (!RenderPlugins.ContainsKey(contentType)) if (!RenderPlugins.ContainsKey(contentType))
return UUID.Zero; return UUID.Zero;
@ -258,7 +253,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.PrimID = primID; updater.PrimID = primID;
updater.ContentType = contentType; updater.ContentType = contentType;
updater.BodyData = data; updater.BodyData = data;
updater.UpdateTimer = updateTimer;
updater.UpdaterID = UUID.Random(); updater.UpdaterID = UUID.Random();
updater.Params = extraParams; updater.Params = extraParams;
updater.BlendWithOldTexture = SetBlending; updater.BlendWithOldTexture = SetBlending;
@ -314,7 +308,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.UpdatePart(part, (UUID)objReusableTextureUUID); updater.UpdatePart(part, (UUID)objReusableTextureUUID);
} }
return updater.UpdaterID; return updater.newTextureID;
} }
private string GenerateReusableTextureKey(string data, string extraParams) private string GenerateReusableTextureKey(string data, string extraParams)
@ -404,17 +398,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public byte FrontAlpha = 255; public byte FrontAlpha = 255;
public string Params; public string Params;
public UUID PrimID; public UUID PrimID;
public bool SetNewFrontAlpha = false;
public UUID SimUUID; public UUID SimUUID;
public UUID UpdaterID; public UUID UpdaterID;
public int UpdateTimer;
public int Face; public int Face;
public int Disp; public int Disp;
public string Url; public string Url;
public UUID newTextureID;
public DynamicTextureUpdater() public DynamicTextureUpdater()
{ {
UpdateTimer = 0;
BodyData = null; BodyData = null;
} }
@ -436,16 +428,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
// FIXME: Need to return the appropriate ID if only a single face is replaced. // FIXME: Need to return the appropriate ID if only a single face is replaced.
oldID = tmptex.DefaultTexture.TextureID; oldID = tmptex.DefaultTexture.TextureID;
// not using parts number of faces because that fails on old meshs
if (Face == ALL_SIDES) if (Face == ALL_SIDES)
{ {
oldID = tmptex.DefaultTexture.TextureID; oldID = tmptex.DefaultTexture.TextureID;
tmptex.DefaultTexture.TextureID = textureID; tmptex.DefaultTexture.TextureID = textureID;
for(int i = 0; i < tmptex.FaceTextures.Length; i++)
{
if(tmptex.FaceTextures[i] != null)
tmptex.FaceTextures[i].TextureID = textureID;
}
} }
else else
{ {
try try
{ {
Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
oldID = texface.TextureID;
texface.TextureID = textureID; texface.TextureID = textureID;
tmptex.FaceTextures[Face] = texface; tmptex.FaceTextures[Face] = texface;
} }
@ -455,10 +454,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
} }
} }
// I'm pretty sure we always want to force this to true
// I'm pretty sure noone whats to set fullbright true if it wasn't true before.
// tmptex.DefaultTexture.Fullbright = true;
part.UpdateTextureEntry(tmptex.GetBytes()); part.UpdateTextureEntry(tmptex.GetBytes());
} }
@ -491,13 +486,26 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (BlendWithOldTexture) if (BlendWithOldTexture)
{ {
Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture; Primitive.TextureEntryFace curFace;
if (defaultFace != null) if(Face == ALL_SIDES)
curFace = part.Shape.Textures.DefaultTexture;
else
{ {
oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString()); try
{
curFace = part.Shape.Textures.GetFace((uint)Face);
}
catch
{
curFace = null;
}
}
if (curFace != null)
{
oldAsset = scene.AssetService.Get(curFace.TextureID.ToString());
if (oldAsset != null) if (oldAsset != null)
assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); assetData = BlendTextures(data, oldAsset.Data, FrontAlpha);
} }
} }
@ -548,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
return asset.FullID; return asset.FullID;
} }
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) private byte[] BlendTextures(byte[] frontImage, byte[] backImage, byte newAlpha)
{ {
ManagedImage managedImage; ManagedImage managedImage;
Image image; Image image;
@ -568,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
Bitmap image2 = new Bitmap(image); Bitmap image2 = new Bitmap(image);
image.Dispose(); image.Dispose();
if (setNewAlpha) if (newAlpha < 255)
SetAlpha(ref image1, newAlpha); SetAlpha(ref image1, newAlpha);
using(Bitmap joint = MergeBitMaps(image1, image2)) using(Bitmap joint = MergeBitMaps(image1, image2))

View File

@ -379,9 +379,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
if (ThreadPool == null) if (ThreadPool == null)
{ {
STPStartInfo startInfo = new STPStartInfo(); STPStartInfo startInfo = new STPStartInfo();
startInfo.IdleTimeout = 20000; startInfo.IdleTimeout = 2000;
startInfo.MaxWorkerThreads = maxThreads; startInfo.MaxWorkerThreads = maxThreads;
startInfo.MinWorkerThreads = 1; startInfo.MinWorkerThreads = 0;
startInfo.ThreadPriority = ThreadPriority.BelowNormal; startInfo.ThreadPriority = ThreadPriority.BelowNormal;
startInfo.StartSuspended = true; startInfo.StartSuspended = true;
startInfo.ThreadPoolName = "ScriptsHttpReq"; startInfo.ThreadPoolName = "ScriptsHttpReq";

View File

@ -77,8 +77,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"", "");
0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -98,8 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -108,8 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -129,8 +126,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -139,8 +135,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"alpha:250", "alpha:250");
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -161,8 +156,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -171,8 +165,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -191,8 +184,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"", "");
0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -213,8 +205,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -223,8 +214,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -253,8 +243,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"1024", "1024");
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -263,8 +252,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"1024", "1024");
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -284,8 +272,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -294,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"alpha:250", "alpha:250");
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
@ -316,8 +302,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -326,8 +311,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID, so.UUID,
m_vrm.GetContentType(), m_vrm.GetContentType(),
dtText, dtText,
"", "");
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }

View File

@ -355,30 +355,22 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
lock (this) lock (this)
{ {
if (alpha == 256) if (alpha == 256)
bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
else
bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
graph = Graphics.FromImage(bitmap);
// this is really just to save people filling the
// background color in their scripts, only do when fully opaque
if (alpha >= 255)
{ {
bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
graph = Graphics.FromImage(bitmap);
using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
{ {
graph.FillRectangle(bgFillBrush, 0, 0, width, height); graph.FillRectangle(bgFillBrush, 0, 0, width, height);
} }
} }
else
for (int w = 0; w < bitmap.Width; w++)
{ {
if (alpha <= 255) bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
graph = Graphics.FromImage(bitmap);
Color newbg = Color.FromArgb(alpha,bgColor);
using (SolidBrush bgFillBrush = new SolidBrush(newbg))
{ {
for (int h = 0; h < bitmap.Height; h++) graph.FillRectangle(bgFillBrush, 0, 0, width, height);
{
bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
}
} }
} }
@ -519,8 +511,32 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
// m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine); // m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine);
if (nextLine.StartsWith("ResetTransf"))
{
graph.ResetTransform();
}
else if (nextLine.StartsWith("TransTransf"))
{
float x = 0;
float y = 0;
GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y);
graph.TranslateTransform(x, y);
}
else if (nextLine.StartsWith("ScaleTransf"))
{
float x = 0;
float y = 0;
GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y);
graph.ScaleTransform(x, y);
}
else if (nextLine.StartsWith("RotTransf"))
{
float x = 0;
GetParams(partsDelimiter, ref nextLine, 9, ref x);
graph.RotateTransform(x);
}
//replace with switch, or even better, do some proper parsing //replace with switch, or even better, do some proper parsing
if (nextLine.StartsWith("MoveTo")) else if (nextLine.StartsWith("MoveTo"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
@ -625,6 +641,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
startPoint.X += endPoint.X; startPoint.X += endPoint.X;
startPoint.Y += endPoint.Y; startPoint.Y += endPoint.Y;
} }
else if (nextLine.StartsWith("FillEllipse"))
{
float x = 0;
float y = 0;
GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y);
endPoint.X = (int)x;
endPoint.Y = (int)y;
graph.FillEllipse(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
startPoint.X += endPoint.X;
startPoint.Y += endPoint.Y;
}
else if (nextLine.StartsWith("FontSize")) else if (nextLine.StartsWith("FontSize"))
{ {
nextLine = nextLine.Remove(0, 8); nextLine = nextLine.Remove(0, 8);
@ -790,6 +817,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
} }
} }
private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x)
{
line = line.Remove(0, startLength);
string[] parts = line.Split(partsDelimiter);
if (parts.Length > 0)
{
string xVal = parts[0].Trim();
x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
}
}
private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y)
{ {
line = line.Remove(0, startLength); line = line.Remove(0, startLength);

View File

@ -658,7 +658,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
public void Process() public void Process()
{ {
_finished = false; _finished = false;
httpThread = WorkManager.StartThread(SendRequest, "HttpRequestThread", ThreadPriority.BelowNormal, true, false, null, int.MaxValue); httpThread = WorkManager.StartThread(SendRequest, "XMLRPCreqThread", ThreadPriority.BelowNormal, true, false, null, int.MaxValue);
} }
/* /*

View File

@ -181,11 +181,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Archive the regions // Archive the regions
Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>(); Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
HashSet<UUID> failedIDs = new HashSet<UUID>();
HashSet<UUID> uncertainAssetsUUIDs = new HashSet<UUID>();
scenesGroup.ForEachScene(delegate(Scene scene) scenesGroup.ForEachScene(delegate(Scene scene)
{ {
string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
ArchiveOneRegion(scene, regionDir, assetUuids); ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs);
}); });
// Archive the assets // Archive the assets
@ -194,22 +196,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{ {
m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
// Asynchronously request all the assets required to perform this archive operation AssetsRequest ar = new AssetsRequest(
AssetsRequest ar
= new AssetsRequest(
new AssetsArchiver(m_archiveWriter), assetUuids, new AssetsArchiver(m_archiveWriter), assetUuids,
failedIDs.Count,
m_rootScene.AssetService, m_rootScene.UserAccountService, m_rootScene.AssetService, m_rootScene.UserAccountService,
m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); m_rootScene.RegionInfo.ScopeID, options, null);
ar.Execute();
WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request"); assetUuids = null;
// CloseArchive() will be called from ReceivedAllAssets()
} }
else else
{ {
m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
CloseArchive(string.Empty); // CloseArchive(string.Empty);
} }
CloseArchive(string.Empty);
} }
catch (Exception e) catch (Exception e)
{ {
@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
} }
} }
private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids) private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids,
HashSet<UUID> failedIDs, HashSet<UUID> uncertainAssetsUUIDs)
{ {
m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name); m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name);
@ -237,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{ {
SceneObjectGroup sceneObject = (SceneObjectGroup)entity; SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) if (!sceneObject.IsDeleted && !sceneObject.IsAttachment && !sceneObject.IsTemporary && !sceneObject.inTransit)
{ {
if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule)) if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule))
{ {
@ -254,17 +255,39 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (SaveAssets) if (SaveAssets)
{ {
UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids); UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids, failedIDs, uncertainAssetsUUIDs);
int prevAssets = assetUuids.Count; int prevAssets = assetUuids.Count;
foreach (SceneObjectGroup sceneObject in sceneObjects) foreach (SceneObjectGroup sceneObject in sceneObjects)
{
int curErrorCntr = assetGatherer.ErrorCount;
int possible = assetGatherer.possibleNotAssetCount;
assetGatherer.AddForInspection(sceneObject); assetGatherer.AddForInspection(sceneObject);
assetGatherer.GatherAll();
curErrorCntr = assetGatherer.ErrorCount - curErrorCntr;
possible = assetGatherer.possibleNotAssetCount - possible;
if(curErrorCntr > 0)
{
m_log.ErrorFormat("[ARCHIVER]: object {0} '{1}', at {2}, contains {3} references to missing or damaged assets",
sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), curErrorCntr);
if(possible > 0)
m_log.WarnFormat("[ARCHIVER Warning]: object also contains {0} references that may be to missing or damaged assets or not a problem", possible);
}
else if(possible > 0)
{
m_log.WarnFormat("[ARCHIVER Warning]: object {0} '{1}', at {2}, contains {3} references that may be to missing or damaged assets or not a problem",
sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), possible);
}
}
assetGatherer.GatherAll(); assetGatherer.GatherAll();
int errors = assetGatherer.FailedUUIDs.Count;
m_log.DebugFormat( m_log.DebugFormat(
"[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", "[ARCHIVER]: {0} region scene objects to save reference {1} possible assets",
sceneObjects.Count, assetUuids.Count - prevAssets); sceneObjects.Count, assetUuids.Count - prevAssets + errors);
if(errors > 0)
m_log.DebugFormat("[ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
} }
if (numObjectsSkippedPermissions > 0) if (numObjectsSkippedPermissions > 0)
@ -572,7 +595,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
foreach (SceneObjectGroup sceneObject in sceneObjects) foreach (SceneObjectGroup sceneObject in sceneObjects)
{ {
//m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
if(sceneObject.IsDeleted || sceneObject.inTransit)
continue;
string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
m_archiveWriter.WriteFile(objectPath, serializedObject); m_archiveWriter.WriteFile(objectPath, serializedObject);

View File

@ -46,7 +46,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// <value> /// <value>
/// Post a message to the log every x assets as a progress bar /// Post a message to the log every x assets as a progress bar
/// </value> /// </value>
protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 50; protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 100;
/// <value> /// <value>
/// Keep a count of the number of assets written so that we can provide status updates /// Keep a count of the number of assets written so that we can provide status updates

View File

@ -61,28 +61,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
Aborted Aborted
}; };
/// <value>
/// Timeout threshold if we still need assets or missing asset notifications but have stopped receiving them
/// from the asset service
/// </value>
protected const int TIMEOUT = 60 * 1000;
/// <value>
/// If a timeout does occur, limit the amount of UUID information put to the console.
/// </value>
protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3;
protected System.Timers.Timer m_requestCallbackTimer;
/// <value>
/// State of this request
/// </value>
private RequestState m_requestState = RequestState.Initial;
/// <value> /// <value>
/// uuids to request /// uuids to request
/// </value> /// </value>
protected IDictionary<UUID, sbyte> m_uuids; protected IDictionary<UUID, sbyte> m_uuids;
private int m_previousErrorsCount;
/// <value> /// <value>
/// Callback used when all the assets requested have been received. /// Callback used when all the assets requested have been received.
@ -104,6 +87,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// </value> /// </value>
private int m_repliesRequired; private int m_repliesRequired;
private System.Timers.Timer m_timeOutTimer;
private bool m_timeout;
/// <value> /// <value>
/// Asset service used to request the assets /// Asset service used to request the assets
/// </value> /// </value>
@ -117,205 +103,98 @@ namespace OpenSim.Region.CoreModules.World.Archiver
protected internal AssetsRequest( protected internal AssetsRequest(
AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids, AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
int previousErrorsCount,
IAssetService assetService, IUserAccountService userService, IAssetService assetService, IUserAccountService userService,
UUID scope, Dictionary<string, object> options, UUID scope, Dictionary<string, object> options,
AssetsRequestCallback assetsRequestCallback) AssetsRequestCallback assetsRequestCallback)
{ {
m_assetsArchiver = assetsArchiver; m_assetsArchiver = assetsArchiver;
m_uuids = uuids; m_uuids = uuids;
m_previousErrorsCount = previousErrorsCount;
m_assetsRequestCallback = assetsRequestCallback; m_assetsRequestCallback = assetsRequestCallback;
m_assetService = assetService; m_assetService = assetService;
m_userAccountService = userService; m_userAccountService = userService;
m_scopeID = scope; m_scopeID = scope;
m_options = options; m_options = options;
m_repliesRequired = uuids.Count; m_repliesRequired = uuids.Count;
// FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
// hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
// so we can properly abort that thread. Or request all assets synchronously, though that would be a more
// radical change
m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
m_requestCallbackTimer.AutoReset = false;
m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
} }
protected internal void Execute() protected internal void Execute()
{ {
m_requestState = RequestState.Running; Culture.SetCurrentCulture();
m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
// We can stop here if there are no assets to fetch // We can stop here if there are no assets to fetch
if (m_repliesRequired == 0) if (m_repliesRequired == 0)
{ {
m_requestState = RequestState.Completed;
PerformAssetsRequestCallback(false); PerformAssetsRequestCallback(false);
return; return;
} }
m_requestCallbackTimer.Enabled = true; m_timeOutTimer = new System.Timers.Timer(60000);
m_timeOutTimer .AutoReset = false;
m_timeOutTimer.Elapsed += OnTimeout;
m_timeout = false;
foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids) foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
{ {
// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); string thiskey = kvp.Key.ToString();
// m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback);
AssetBase asset = m_assetService.Get(kvp.Key.ToString());
PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset);
}
}
protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args)
{
bool timedOut = true;
try try
{ {
lock (this) m_timeOutTimer.Enabled = true;
{ AssetBase asset = m_assetService.Get(thiskey);
// Take care of the possibilty that this thread started but was paused just outside the lock before if(m_timeout)
// the final request came in (assuming that such a thing is possible)
if (m_requestState == RequestState.Completed)
{
timedOut = false;
return;
}
m_requestState = RequestState.Aborted;
}
// Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure
// case anyway.
List<UUID> uuids = new List<UUID>();
foreach (UUID uuid in m_uuids.Keys)
{
uuids.Add(uuid);
}
foreach (UUID uuid in m_foundAssetUuids)
{
uuids.Remove(uuid);
}
foreach (UUID uuid in m_notFoundAssetUuids)
{
uuids.Remove(uuid);
}
m_log.ErrorFormat(
"[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count);
int i = 0;
foreach (UUID uuid in uuids)
{
m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid);
if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT)
break; break;
m_timeOutTimer.Enabled = false;
if(asset == null)
{
m_notFoundAssetUuids.Add(new UUID(thiskey));
continue;
} }
if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT) sbyte assetType = kvp.Value;
m_log.ErrorFormat( if (asset != null && assetType == (sbyte)AssetType.Unknown)
"[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT);
m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE.");
}
catch (Exception e)
{ {
m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace); m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType));
} asset.Type = assetType;
finally
{
if (timedOut)
WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback");
}
} }
protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset)
{
// Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
{
m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
fetchedAsset.Type = (sbyte)assetType;
}
AssetRequestCallback(fetchedAssetID, this, fetchedAsset);
}
/// <summary>
/// Called back by the asset cache when it has the asset
/// </summary>
/// <param name="assetID"></param>
/// <param name="asset"></param>
public void AssetRequestCallback(string id, object sender, AssetBase asset)
{
Culture.SetCurrentCulture();
try
{
lock (this)
{
//m_log.DebugFormat("[ARCHIVER]: Received callback for asset {0}", id);
m_requestCallbackTimer.Stop();
if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed))
{
m_log.WarnFormat(
"[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.",
id, m_requestState);
return;
}
if (asset != null)
{
// m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id);
m_foundAssetUuids.Add(asset.FullID); m_foundAssetUuids.Add(asset.FullID);
m_assetsArchiver.WriteAsset(PostProcess(asset)); m_assetsArchiver.WriteAsset(PostProcess(asset));
} }
else
{
// m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id);
m_notFoundAssetUuids.Add(new UUID(id));
}
if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired)
{
m_requestState = RequestState.Completed;
if(m_notFoundAssetUuids.Count == 0)
m_log.DebugFormat(
"[ARCHIVER]: Successfully added {0} assets",
m_foundAssetUuids.Count);
else
m_log.DebugFormat(
"[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)",
m_foundAssetUuids.Count, m_notFoundAssetUuids.Count);
// We want to stop using the asset cache thread asap
// as we now need to do the work of producing the rest of the archive
WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback");
}
else
{
m_requestCallbackTimer.Start();
}
}
}
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e); m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e);
} }
} }
m_timeOutTimer.Dispose();
int totalerrors = m_notFoundAssetUuids.Count + m_previousErrorsCount;
if(m_timeout)
m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count);
else if(totalerrors == 0)
m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count);
else
m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} of total possible assets requested were not found, were damaged or were not assets)",
m_foundAssetUuids.Count, totalerrors);
PerformAssetsRequestCallback(m_timeout);
}
private void OnTimeout(object source, ElapsedEventArgs args)
{
m_timeout = true;
}
/// <summary> /// <summary>
/// Perform the callback on the original requester of the assets /// Perform the callback on the original requester of the assets
/// </summary> /// </summary>
protected void PerformAssetsRequestCallback(object o) private void PerformAssetsRequestCallback(object o)
{ {
if(m_assetsRequestCallback == null)
return;
Culture.SetCurrentCulture(); Culture.SetCurrentCulture();
Boolean timedOut = (Boolean)o; Boolean timedOut = (Boolean)o;
@ -331,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
} }
} }
protected AssetBase PostProcess(AssetBase asset) private AssetBase PostProcess(AssetBase asset)
{ {
if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
{ {

View File

@ -176,6 +176,14 @@ namespace OpenSim.Region.CoreModules.World.Land
} }
} }
public void SendParcelsOverlay(IClientAPI client)
{
if (m_landManagementModule != null)
{
m_landManagementModule.SendParcelOverlay(client);
}
}
public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
{ {
if (m_landManagementModule != null) if (m_landManagementModule != null)

View File

@ -44,14 +44,13 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name='isReuseable'></param> /// <param name='isReuseable'></param>
void ReturnData(UUID id, IDynamicTexture texture); void ReturnData(UUID id, IDynamicTexture texture);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
int updateTimer); bool SetBlending, byte AlphaValue);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
int updateTimer, bool SetBlending, byte AlphaValue); bool SetBlending, int disp, byte AlphaValue, int face);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face); UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams);
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer);
/// Apply a dynamically generated texture to all sides of the given prim. The texture is not persisted to the /// Apply a dynamically generated texture to all sides of the given prim. The texture is not persisted to the
/// asset service. /// asset service.
@ -62,8 +61,6 @@ namespace OpenSim.Region.Framework.Interfaces
/// based texture or "image" to create a texture from an image at a particular URL</param> /// based texture or "image" to create a texture from an image at a particular URL</param>
/// <param name="data">The data for the generator</param> /// <param name="data">The data for the generator</param>
/// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param> /// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param>
/// <param name="updateTimer">If zero, the image is never updated after the first generation. If positive
/// the image is updated at the given interval. Not implemented for </param>
/// <param name="SetBlending"> /// <param name="SetBlending">
/// If true, the newly generated texture is blended with the appropriate existing ones on the prim /// If true, the newly generated texture is blended with the appropriate existing ones on the prim
/// </param> /// </param>
@ -76,7 +73,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
/// </returns> /// </returns>
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer, bool SetBlending, byte AlphaValue); bool SetBlending, byte AlphaValue);
/// <summary> /// <summary>
/// Apply a dynamically generated texture to the given prim. /// Apply a dynamically generated texture to the given prim.
@ -87,8 +84,6 @@ namespace OpenSim.Region.Framework.Interfaces
/// based texture or "image" to create a texture from an image at a particular URL</param> /// based texture or "image" to create a texture from an image at a particular URL</param>
/// <param name="data">The data for the generator</param> /// <param name="data">The data for the generator</param>
/// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param> /// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param>
/// <param name="updateTimer">If zero, the image is never updated after the first generation. If positive
/// the image is updated at the given interval. Not implemented for </param>
/// <param name="SetBlending"> /// <param name="SetBlending">
/// If true, the newly generated texture is blended with the appropriate existing ones on the prim /// If true, the newly generated texture is blended with the appropriate existing ones on the prim
/// </param> /// </param>
@ -109,9 +104,8 @@ namespace OpenSim.Region.Framework.Interfaces
/// to obtain it directly from the SceneObjectPart. For instance, if ALL_SIDES is set then this texture /// to obtain it directly from the SceneObjectPart. For instance, if ALL_SIDES is set then this texture
/// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
/// </returns> /// </returns>
UUID AddDynamicTextureData( UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
UUID simID, UUID primID, string contentType, string data, string extraParams, bool SetBlending, int disp, byte AlphaValue, int face);
int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face);
void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
out double xSize, out double ySize); out double xSize, out double ySize);

View File

@ -116,16 +116,20 @@ namespace OpenSim.Region.Framework.Scenes
public static void PartCollisionSound(SceneObjectPart part, List<CollisionForSoundInfo> collidersinfolist) public static void PartCollisionSound(SceneObjectPart part, List<CollisionForSoundInfo> collidersinfolist)
{ {
if (part.CollisionSoundType < 0)
return;
if (collidersinfolist.Count == 0 || part == null) if (collidersinfolist.Count == 0 || part == null)
return; return;
if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0) if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
return; return;
if (part.ParentGroup == null) SceneObjectGroup sog = part.ParentGroup;
if (sog == null || sog.IsDeleted || sog.inTransit)
return; return;
if (part.CollisionSoundType < 0) if(sog.CollisionSoundThrottled(part.CollisionSoundType))
return; return;
float volume = part.CollisionSoundVolume; float volume = part.CollisionSoundVolume;
@ -189,15 +193,23 @@ namespace OpenSim.Region.Framework.Scenes
continue; continue;
} }
SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id); SceneObjectPart otherPart = sog.Scene.GetSceneObjectPart(id);
if (otherPart != null) if (otherPart != null)
{ {
if (otherPart.CollisionSoundType < 0 || otherPart.VolumeDetectActive) SceneObjectGroup othersog = otherPart.ParentGroup;
if(othersog == null || othersog.IsDeleted || othersog.inTransit)
continue;
int otherType = otherPart.CollisionSoundType;
if (otherType < 0 || otherPart.VolumeDetectActive)
continue; continue;
if (!HaveSound) if (!HaveSound)
{ {
if (otherPart.CollisionSoundType == 1) if(othersog.CollisionSoundThrottled(otherType))
continue;
if (otherType == 1)
{ {
soundID = otherPart.CollisionSound; soundID = otherPart.CollisionSound;
volume = otherPart.CollisionSoundVolume; volume = otherPart.CollisionSoundVolume;
@ -206,7 +218,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
if (otherPart.CollisionSoundType == 2) if (otherType == 2)
{ {
volume = otherPart.CollisionSoundVolume; volume = otherPart.CollisionSoundVolume;
if (volume == 0.0f) if (volume == 0.0f)

View File

@ -855,7 +855,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <see cref="Scene.DeleteSceneObject"/>, /// <see cref="Scene.DeleteSceneObject"/>,
/// <see cref="Scene.SelectPrim"/>, /// <see cref="Scene.SelectPrim"/>,
/// <see cref="Scene.DeselectPrim"/>, /// <see cref="Scene.DeselectPrim"/>,
/// <see cref="SceneObjectGroup.UpdatePrimFlags"/>, /// <see cref="SceneObjectGroup.UpdateFlags"/>,
/// <see cref="SceneObjectGroup.AbsolutePosition"/> /// <see cref="SceneObjectGroup.AbsolutePosition"/>
/// </remarks> /// </remarks>
public event ParcelPrimCountTainted OnParcelPrimCountTainted; public event ParcelPrimCountTainted OnParcelPrimCountTainted;

View File

@ -295,6 +295,7 @@ namespace OpenSim.Region.Framework.Scenes
lock (m_frames) lock (m_frames)
{ {
KeyframeTimer.Add(this); KeyframeTimer.Add(this);
m_lasttickMS = Util.GetTimeStampMS();
m_timerStopped = false; m_timerStopped = false;
} }
} }
@ -326,8 +327,8 @@ namespace OpenSim.Region.Framework.Scenes
newMotion.m_selected = true; newMotion.m_selected = true;
} }
newMotion.m_timerStopped = false; // newMotion.m_timerStopped = false;
newMotion.m_running = true; // newMotion.m_running = true;
newMotion.m_isCrossing = false; newMotion.m_isCrossing = false;
newMotion.m_waitingCrossing = false; newMotion.m_waitingCrossing = false;
} }
@ -483,9 +484,10 @@ namespace OpenSim.Region.Framework.Scenes
m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.Velocity = Vector3.Zero;
m_group.RootPart.AngularVelocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero;
m_group.SendGroupRootTerseUpdate(); // m_group.SendGroupRootTerseUpdate();
// m_group.RootPart.ScheduleTerseUpdate(); m_group.RootPart.ScheduleTerseUpdate();
m_frames.Clear(); m_frames.Clear();
m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
} }
public void Pause() public void Pause()
@ -496,8 +498,9 @@ namespace OpenSim.Region.Framework.Scenes
m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.Velocity = Vector3.Zero;
m_group.RootPart.AngularVelocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero;
m_skippedUpdates = 1000; m_skippedUpdates = 1000;
m_group.SendGroupRootTerseUpdate(); // m_group.SendGroupRootTerseUpdate();
// m_group.RootPart.ScheduleTerseUpdate(); m_group.RootPart.ScheduleTerseUpdate();
m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
} }
public void Suspend() public void Suspend()
@ -644,15 +647,16 @@ namespace OpenSim.Region.Framework.Scenes
m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.Velocity = Vector3.Zero;
m_group.RootPart.AngularVelocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero;
m_group.SendGroupRootTerseUpdate(); // m_group.SendGroupRootTerseUpdate();
m_group.RootPart.ScheduleTerseUpdate();
m_frames.Clear(); m_frames.Clear();
} }
Vector3 m_lastPosUpdate; [NonSerialized()] Vector3 m_lastPosUpdate;
Quaternion m_lastRotationUpdate; [NonSerialized()] Quaternion m_lastRotationUpdate;
Vector3 m_currentVel; [NonSerialized()] Vector3 m_currentVel;
int m_skippedUpdates; [NonSerialized()] int m_skippedUpdates;
[NonSerialized()] double m_lasttickMS;
private void DoOnTimer(double tickDuration) private void DoOnTimer(double tickDuration)
{ {
@ -673,7 +677,8 @@ namespace OpenSim.Region.Framework.Scenes
{ {
m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.Velocity = Vector3.Zero;
m_skippedUpdates = 1000; m_skippedUpdates = 1000;
m_group.SendGroupRootTerseUpdate(); // m_group.SendGroupRootTerseUpdate();
m_group.RootPart.ScheduleTerseUpdate();
} }
return; return;
} }
@ -696,6 +701,8 @@ namespace OpenSim.Region.Framework.Scenes
return; return;
} }
double nowMS = Util.GetTimeStampMS();
if (m_frames.Count == 0) if (m_frames.Count == 0)
{ {
lock (m_frames) lock (m_frames)
@ -716,10 +723,16 @@ namespace OpenSim.Region.Framework.Scenes
m_currentVel /= (m_currentFrame.TimeMS * 0.001f); m_currentVel /= (m_currentFrame.TimeMS * 0.001f);
m_currentFrame.TimeMS += (int)tickDuration; m_currentFrame.TimeMS += (int)tickDuration;
m_lasttickMS = nowMS - 50f;
update = true; update = true;
} }
m_currentFrame.TimeMS -= (int)tickDuration; int elapsed = (int)(nowMS - m_lasttickMS);
if( elapsed > 3 * tickDuration)
elapsed = (int)tickDuration;
m_currentFrame.TimeMS -= elapsed;
m_lasttickMS = nowMS;
// Do the frame processing // Do the frame processing
double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration; double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration;
@ -752,7 +765,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
bool lastSteps = remainingSteps < 4; // bool lastSteps = remainingSteps < 4;
Vector3 currentPosition = m_group.AbsolutePosition; Vector3 currentPosition = m_group.AbsolutePosition;
Vector3 motionThisFrame = (Vector3)m_currentFrame.Position - currentPosition; Vector3 motionThisFrame = (Vector3)m_currentFrame.Position - currentPosition;
motionThisFrame /= (float)remainingSteps; motionThisFrame /= (float)remainingSteps;
@ -766,20 +780,22 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed);
step.Normalize(); step.Normalize();
m_group.RootPart.RotationOffset = step; m_group.RootPart.RotationOffset = step;
/*
if (Math.Abs(step.X - m_lastRotationUpdate.X) > 0.001f if (Math.Abs(step.X - m_lastRotationUpdate.X) > 0.001f
|| Math.Abs(step.Y - m_lastRotationUpdate.Y) > 0.001f || Math.Abs(step.Y - m_lastRotationUpdate.Y) > 0.001f
|| Math.Abs(step.Z - m_lastRotationUpdate.Z) > 0.001f) || Math.Abs(step.Z - m_lastRotationUpdate.Z) > 0.001f)
update = true; update = true;
*/
} }
m_group.AbsolutePosition = m_nextPosition; m_group.AbsolutePosition = m_nextPosition;
if(lastSteps) // if(lastSteps)
m_group.RootPart.Velocity = Vector3.Zero; // m_group.RootPart.Velocity = Vector3.Zero;
else // else
m_group.RootPart.Velocity = m_currentVel; m_group.RootPart.Velocity = m_currentVel;
/*
if(!update && ( if(!update && (
lastSteps || // lastSteps ||
m_skippedUpdates * tickDuration > 0.5 || m_skippedUpdates * tickDuration > 0.5 ||
Math.Abs(m_nextPosition.X - currentPosition.X) > 5f || Math.Abs(m_nextPosition.X - currentPosition.X) > 5f ||
Math.Abs(m_nextPosition.Y - currentPosition.Y) > 5f || Math.Abs(m_nextPosition.Y - currentPosition.Y) > 5f ||
@ -790,15 +806,16 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
m_skippedUpdates++; m_skippedUpdates++;
*/
}
if(update)
{
m_lastPosUpdate = m_nextPosition;
m_lastRotationUpdate = m_group.GroupRotation;
m_skippedUpdates = 0;
m_group.SendGroupRootTerseUpdate();
} }
// if(update)
// {
// m_lastPosUpdate = m_nextPosition;
// m_lastRotationUpdate = m_group.GroupRotation;
// m_skippedUpdates = 0;
// m_group.SendGroupRootTerseUpdate();
m_group.RootPart.ScheduleTerseUpdate();
// }
} }
public Byte[] Serialize() public Byte[] Serialize()
@ -842,8 +859,8 @@ namespace OpenSim.Region.Framework.Scenes
{ {
m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.Velocity = Vector3.Zero;
m_skippedUpdates = 1000; m_skippedUpdates = 1000;
m_group.SendGroupRootTerseUpdate(); // m_group.SendGroupRootTerseUpdate();
// m_group.RootPart.ScheduleTerseUpdate(); m_group.RootPart.ScheduleTerseUpdate();
} }
} }
@ -855,8 +872,8 @@ namespace OpenSim.Region.Framework.Scenes
{ {
m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.Velocity = Vector3.Zero;
m_skippedUpdates = 1000; m_skippedUpdates = 1000;
m_group.SendGroupRootTerseUpdate(); // m_group.SendGroupRootTerseUpdate();
// m_group.RootPart.ScheduleTerseUpdate(); m_group.RootPart.ScheduleTerseUpdate();
if (m_running) if (m_running)
{ {

View File

@ -425,25 +425,25 @@ namespace OpenSim.Region.Framework.Scenes
private void XWfloat(string name, float f) private void XWfloat(string name, float f)
{ {
writer.WriteElementString(name, f.ToString(Utils.EnUsCulture)); writer.WriteElementString(name, f.ToString(Culture.FormatProvider));
} }
private void XWVector(string name, Vector3 vec) private void XWVector(string name, Vector3 vec)
{ {
writer.WriteStartElement(name); writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture)); writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture)); writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture)); writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
writer.WriteEndElement(); writer.WriteEndElement();
} }
private void XWQuat(string name, Quaternion quat) private void XWQuat(string name, Quaternion quat)
{ {
writer.WriteStartElement(name); writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture)); writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture)); writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture)); writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture)); writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
writer.WriteEndElement(); writer.WriteEndElement();
} }

View File

@ -1651,10 +1651,11 @@ namespace OpenSim.Region.Framework.Scenes
physicsMS2 = (float)(tmpMS2 - tmpMS); physicsMS2 = (float)(tmpMS2 - tmpMS);
tmpMS = tmpMS2; tmpMS = tmpMS2;
/*
// Apply any pending avatar force input to the avatar's velocity // Apply any pending avatar force input to the avatar's velocity
if (Frame % m_update_entitymovement == 0) if (Frame % m_update_entitymovement == 0)
m_sceneGraph.UpdateScenePresenceMovement(); m_sceneGraph.UpdateScenePresenceMovement();
*/
if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations) if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations)
{ {
m_sendingCoarseLocations = true; m_sendingCoarseLocations = true;
@ -1942,7 +1943,6 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (!m_backingup) if (!m_backingup)
{ {
m_backingup = true;
WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0})", Name)); WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0})", Name));
} }
} }
@ -1970,41 +1970,61 @@ namespace OpenSim.Region.Framework.Scenes
public void Backup(bool forced) public void Backup(bool forced)
{ {
lock (m_returns) lock (m_returns)
{
if(m_backingup)
{
m_log.WarnFormat("[Scene] Backup of {0} already running. New call skipped", RegionInfo.RegionName);
return;
}
m_backingup = true;
try
{ {
EventManager.TriggerOnBackup(SimulationDataService, forced); EventManager.TriggerOnBackup(SimulationDataService, forced);
if(m_returns.Count == 0)
return;
IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
if (tr == null)
return;
uint unixtime = (uint)Util.UnixTimeSinceEpoch();
uint estateid = RegionInfo.EstateSettings.ParentEstateID;
Guid regionguid = RegionInfo.RegionID.Guid;
foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns) foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
{ {
UUID transaction = UUID.Random();
GridInstantMessage msg = new GridInstantMessage(); GridInstantMessage msg = new GridInstantMessage();
msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server msg.fromAgentID = Guid.Empty; // From server
msg.toAgentID = new Guid(ret.Key.ToString()); msg.toAgentID = ret.Key.Guid;
msg.imSessionID = new Guid(transaction.ToString()); msg.imSessionID = Guid.NewGuid();
msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.timestamp = unixtime;
msg.fromAgentName = "Server"; msg.fromAgentName = "Server";
msg.dialog = (byte)19; // Object msg msg.dialog = 19; // Object msg
msg.fromGroup = false; msg.fromGroup = false;
msg.offline = (byte)1; msg.offline = 1;
msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; msg.ParentEstateID = estateid;
msg.Position = Vector3.Zero; msg.Position = Vector3.Zero;
msg.RegionID = RegionInfo.RegionID.Guid; msg.RegionID = regionguid;
// We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
msg.binaryBucket = Util.StringToBytes256("\0"); msg.binaryBucket = new Byte[1] {0};
if (ret.Value.count > 1) if (ret.Value.count > 1)
msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
else else
msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
if (tr != null)
tr.SendInstantMessage(msg, delegate(bool success) { }); tr.SendInstantMessage(msg, delegate(bool success) { });
} }
m_returns.Clear(); m_returns.Clear();
}
finally
{
m_backingup = false; m_backingup = false;
} }
} }
}
/// <summary> /// <summary>
/// Synchronous force backup. For deletes and links/unlinks /// Synchronous force backup. For deletes and links/unlinks
@ -4805,16 +4825,34 @@ Label_GroupsDone:
public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position,
Vector3 lookat, uint teleportFlags) Vector3 lookat, uint teleportFlags)
{ {
GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); if (EntityTransferModule == null)
{
m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
return;
}
if (region == null) ScenePresence sp = GetScenePresence(remoteClient.AgentId);
if (sp == null || sp.IsDeleted || sp.IsInTransit)
return;
ulong regionHandle = 0;
if(regionName == RegionInfo.RegionName)
regionHandle = RegionInfo.RegionHandle;
else
{
GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName);
if (region != null)
regionHandle = region.RegionHandle;
}
if(regionHandle == 0)
{ {
// can't find the region: Tell viewer and abort // can't find the region: Tell viewer and abort
remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found.");
return; return;
} }
RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); EntityTransferModule.Teleport(sp, regionHandle, position, lookat, teleportFlags);
} }
/// <summary> /// <summary>
@ -4828,19 +4866,17 @@ Label_GroupsDone:
public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position,
Vector3 lookAt, uint teleportFlags) Vector3 lookAt, uint teleportFlags)
{ {
ScenePresence sp = GetScenePresence(remoteClient.AgentId); if (EntityTransferModule == null)
if (sp != null)
{
if (EntityTransferModule != null)
{
EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
}
else
{ {
m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator."); return;
}
} }
ScenePresence sp = GetScenePresence(remoteClient.AgentId);
if (sp == null || sp.IsDeleted || sp.IsInTransit)
return;
EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
} }
public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying)

View File

@ -1649,7 +1649,7 @@ namespace OpenSim.Region.Framework.Scenes
else // else turn it off else // else turn it off
vdtc = false; vdtc = false;
group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc); group.UpdateFlags(UsePhysics, SetTemporary, SetPhantom, vdtc);
} }
else else
{ {

View File

@ -1259,6 +1259,8 @@ namespace OpenSim.Region.Framework.Scenes
set { m_LoopSoundSlavePrims = value; } set { m_LoopSoundSlavePrims = value; }
} }
private double m_lastCollisionSoundMS;
/// <summary> /// <summary>
/// The UUID for the region this object is in. /// The UUID for the region this object is in.
/// </summary> /// </summary>
@ -1336,7 +1338,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public SceneObjectGroup() public SceneObjectGroup()
{ {
m_lastCollisionSoundMS = Util.GetTimeStampMS() + 1000.0;
} }
/// <summary> /// <summary>
@ -2716,35 +2718,22 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.KeyframeMotion.Stop(); RootPart.KeyframeMotion.Stop();
RootPart.KeyframeMotion = null; RootPart.KeyframeMotion = null;
} }
UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); UpdateFlags(usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
} }
public void ScriptSetTemporaryStatus(bool makeTemporary) public void ScriptSetTemporaryStatus(bool makeTemporary)
{ {
UpdatePrimFlags(RootPart.LocalId, UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect); UpdateFlags(UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect);
} }
public void ScriptSetPhantomStatus(bool makePhantom) public void ScriptSetPhantomStatus(bool makePhantom)
{ {
UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect); UpdateFlags(UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect);
} }
public void ScriptSetVolumeDetect(bool makeVolumeDetect) public void ScriptSetVolumeDetect(bool makeVolumeDetect)
{ {
UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect); UpdateFlags(UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect);
/*
ScriptSetPhantomStatus(false); // What ever it was before, now it's not phantom anymore
if (PhysActor != null) // Should always be the case now
{
PhysActor.SetVolumeDetect(param);
}
if (param != 0)
AddFlag(PrimFlags.Phantom);
ScheduleFullUpdate();
*/
} }
public void applyImpulse(Vector3 impulse) public void applyImpulse(Vector3 impulse)
@ -4029,14 +4018,13 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="SetTemporary"></param> /// <param name="SetTemporary"></param>
/// <param name="SetPhantom"></param> /// <param name="SetPhantom"></param>
/// <param name="SetVolumeDetect"></param> /// <param name="SetVolumeDetect"></param>
public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) public void UpdateFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect)
{ {
if (m_scene == null || IsDeleted)
return;
HasGroupChanged = true; HasGroupChanged = true;
SceneObjectPart selectionPart = GetPart(localID);
if (Scene != null)
{
if (SetTemporary) if (SetTemporary)
{ {
DetachFromBackup(); DetachFromBackup();
@ -4051,14 +4039,10 @@ namespace OpenSim.Region.Framework.Scenes
AttachToBackup(); AttachToBackup();
} }
m_scene.EventManager.TriggerParcelPrimCountTainted();
}
if (selectionPart != null)
{
SceneObjectPart[] parts = m_parts.GetArray(); SceneObjectPart[] parts = m_parts.GetArray();
if (Scene != null && UsePhysics) if (UsePhysics)
{ {
int maxprims = m_scene.m_linksetPhysCapacity; int maxprims = m_scene.m_linksetPhysCapacity;
bool checkShape = (maxprims > 0 && bool checkShape = (maxprims > 0 &&
@ -4106,7 +4090,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false); m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
}
m_scene.EventManager.TriggerParcelPrimCountTainted();
} }
public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data) public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
@ -5528,7 +5513,33 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public bool CollisionSoundThrottled(int collisionSoundType)
{
double time = m_lastCollisionSoundMS;
// m_lastCollisionSoundMS = Util.GetTimeStampMS();
// time = m_lastCollisionSoundMS - time;
double now = Util.GetTimeStampMS();
time = now - time;
switch (collisionSoundType)
{
case 0: // default sounds
case 2: // default sounds with volume set by script
if(time < 300.0)
return true;
break;
case 1: // selected sound
if(time < 200.0)
return true;
break;
default:
break;
}
m_lastCollisionSoundMS = now;
return false;
}
#endregion #endregion
} }
} }

View File

@ -329,7 +329,8 @@ namespace OpenSim.Region.Framework.Scenes
private byte[] m_TextureAnimation; private byte[] m_TextureAnimation;
private byte m_clickAction; private byte m_clickAction;
private Color m_color = Color.Black; private Color m_color = Color.Black;
private readonly List<uint> m_lastColliders = new List<uint>(); private List<uint> m_lastColliders = new List<uint>();
private bool m_lastLandCollide;
private int m_linkNum; private int m_linkNum;
private int m_scriptAccessPin; private int m_scriptAccessPin;
@ -369,9 +370,9 @@ namespace OpenSim.Region.Framework.Scenes
protected Vector3 m_lastPosition; protected Vector3 m_lastPosition;
protected Quaternion m_lastRotation; protected Quaternion m_lastRotation;
protected Vector3 m_lastVelocity; protected Vector3 m_lastVelocity;
protected Vector3 m_lastAcceleration; protected Vector3 m_lastAcceleration; // acceleration is a derived var with high noise
protected Vector3 m_lastAngularVelocity; protected Vector3 m_lastAngularVelocity;
protected int m_lastUpdateSentTime; protected double m_lastUpdateSentTime;
protected float m_buoyancy = 0.0f; protected float m_buoyancy = 0.0f;
protected Vector3 m_force; protected Vector3 m_force;
protected Vector3 m_torque; protected Vector3 m_torque;
@ -809,7 +810,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// If this is a linkset, we don't want the physics engine mucking up our group position here. // If this is a linkset, we don't want the physics engine mucking up our group position here.
PhysicsActor actor = PhysActor; PhysicsActor actor = PhysActor;
if (ParentID == 0) if (_parentID == 0)
{ {
if (actor != null) if (actor != null)
m_groupPosition = actor.Position; m_groupPosition = actor.Position;
@ -838,7 +839,7 @@ namespace OpenSim.Region.Framework.Scenes
try try
{ {
// Root prim actually goes at Position // Root prim actually goes at Position
if (ParentID == 0) if (_parentID == 0)
{ {
actor.Position = value; actor.Position = value;
} }
@ -880,7 +881,7 @@ namespace OpenSim.Region.Framework.Scenes
ParentGroup.InvalidBoundsRadius(); ParentGroup.InvalidBoundsRadius();
PhysicsActor actor = PhysActor; PhysicsActor actor = PhysActor;
if (ParentID != 0 && actor != null) if (_parentID != 0 && actor != null)
{ {
actor.Position = GetWorldPosition(); actor.Position = GetWorldPosition();
actor.Orientation = GetWorldRotation(); actor.Orientation = GetWorldRotation();
@ -940,7 +941,7 @@ namespace OpenSim.Region.Framework.Scenes
PhysicsActor actor = PhysActor; PhysicsActor actor = PhysActor;
// If this is a root of a linkset, the real rotation is what the physics engine thinks. // If this is a root of a linkset, the real rotation is what the physics engine thinks.
// If not a root prim, the offset rotation is computed by SOG and is relative to the root. // If not a root prim, the offset rotation is computed by SOG and is relative to the root.
if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) if (_parentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null)
m_rotationOffset = actor.Orientation; m_rotationOffset = actor.Orientation;
return m_rotationOffset; return m_rotationOffset;
@ -957,7 +958,7 @@ namespace OpenSim.Region.Framework.Scenes
try try
{ {
// Root prim gets value directly // Root prim gets value directly
if (ParentID == 0) if (_parentID == 0)
{ {
actor.Orientation = value; actor.Orientation = value;
//m_log.Info("[PART]: RO1:" + actor.Orientation.ToString()); //m_log.Info("[PART]: RO1:" + actor.Orientation.ToString());
@ -1103,8 +1104,8 @@ namespace OpenSim.Region.Framework.Scenes
{ {
get get
{ {
if (m_text.Length > 255) if (m_text.Length > 256) // yes > 254
return m_text.Substring(0, 254); return m_text.Substring(0, 256);
return m_text; return m_text;
} }
set { m_text = value; } set { m_text = value; }
@ -1258,6 +1259,9 @@ namespace OpenSim.Region.Framework.Scenes
{ {
get get
{ {
if (_parentID == 0)
return GroupPosition;
return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset); return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
} }
} }
@ -1379,7 +1383,8 @@ namespace OpenSim.Region.Framework.Scenes
public UUID LastOwnerID public UUID LastOwnerID
{ {
get { return _lastOwnerID; } get { return _lastOwnerID; }
set { _lastOwnerID = value; } set {
_lastOwnerID = value; }
} }
public UUID RezzerID public UUID RezzerID
@ -2422,7 +2427,7 @@ namespace OpenSim.Region.Framework.Scenes
PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
PhysActor.OnOutOfBounds += PhysicsOutOfBounds; PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
if (ParentID != 0 && ParentID != LocalId) if (_parentID != 0 && _parentID != LocalId)
{ {
PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
@ -2788,12 +2793,13 @@ namespace OpenSim.Region.Framework.Scenes
{ {
ColliderArgs colliderArgs = new ColliderArgs(); ColliderArgs colliderArgs = new ColliderArgs();
List<DetectedObject> colliding = new List<DetectedObject>(); List<DetectedObject> colliding = new List<DetectedObject>();
Scene parentScene = ParentGroup.Scene;
foreach (uint localId in colliders) foreach (uint localId in colliders)
{ {
if (localId == 0) if (localId == 0)
continue; continue;
SceneObjectPart obj = ParentGroup.Scene.GetSceneObjectPart(localId); SceneObjectPart obj = parentScene.GetSceneObjectPart(localId);
if (obj != null) if (obj != null)
{ {
if (!dest.CollisionFilteredOut(obj.UUID, obj.Name)) if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
@ -2801,7 +2807,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
ScenePresence av = ParentGroup.Scene.GetScenePresence(localId); ScenePresence av = parentScene.GetScenePresence(localId);
if (av != null && (!av.IsChildAgent)) if (av != null && (!av.IsChildAgent))
{ {
if (!dest.CollisionFilteredOut(av.UUID, av.Name)) if (!dest.CollisionFilteredOut(av.UUID, av.Name))
@ -2874,10 +2880,13 @@ namespace OpenSim.Region.Framework.Scenes
public void PhysicsCollision(EventArgs e) public void PhysicsCollision(EventArgs e)
{ {
if (ParentGroup.Scene == null || ParentGroup.IsDeleted) if (ParentGroup.Scene == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
return; return;
// this a thread from physics ( heartbeat ) // this a thread from physics ( heartbeat )
bool thisHitLand = false;
bool startLand = false;
bool endedLand = false;
CollisionEventUpdate a = (CollisionEventUpdate)e; CollisionEventUpdate a = (CollisionEventUpdate)e;
Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList; Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList;
@ -2887,13 +2896,17 @@ namespace OpenSim.Region.Framework.Scenes
if (collissionswith.Count == 0) if (collissionswith.Count == 0)
{ {
if (m_lastColliders.Count == 0) if (m_lastColliders.Count == 0 && !m_lastLandCollide)
return; // nothing to do return; // nothing to do
endedLand = m_lastLandCollide;
m_lastLandCollide = false;
foreach (uint localID in m_lastColliders) foreach (uint localID in m_lastColliders)
{ {
endedColliders.Add(localID); endedColliders.Add(localID);
} }
m_lastColliders.Clear(); m_lastColliders.Clear();
} }
else else
@ -2908,6 +2921,25 @@ namespace OpenSim.Region.Framework.Scenes
ContactPoint curcontact; ContactPoint curcontact;
foreach (uint id in collissionswith.Keys) foreach (uint id in collissionswith.Keys)
{
if(id == 0)
{
thisHitLand = true;
if (!m_lastLandCollide)
{
startLand = true;
curcontact = collissionswith[id];
if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
{
soundinfo = new CollisionForSoundInfo();
soundinfo.colliderID = id;
soundinfo.position = curcontact.Position;
soundinfo.relativeVel = curcontact.RelativeSpeed;
soundinfolist.Add(soundinfo);
}
}
}
else
{ {
thisHitColliders.Add(id); thisHitColliders.Add(id);
if (!m_lastColliders.Contains(id)) if (!m_lastColliders.Contains(id))
@ -2926,15 +2958,25 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
}
else else
{ {
foreach (uint id in collissionswith.Keys) foreach (uint id in collissionswith.Keys)
{
if(id == 0)
{
thisHitLand = true;
if (!m_lastLandCollide)
startLand = true;
}
else
{ {
thisHitColliders.Add(id); thisHitColliders.Add(id);
if (!m_lastColliders.Contains(id)) if (!m_lastColliders.Contains(id))
startedColliders.Add(id); startedColliders.Add(id);
} }
} }
}
// calculate things that ended colliding // calculate things that ended colliding
foreach (uint localID in m_lastColliders) foreach (uint localID in m_lastColliders)
@ -2951,22 +2993,32 @@ namespace OpenSim.Region.Framework.Scenes
foreach (uint localID in endedColliders) foreach (uint localID in endedColliders)
m_lastColliders.Remove(localID); m_lastColliders.Remove(localID);
if(m_lastLandCollide && !thisHitLand)
endedLand = true;
m_lastLandCollide = thisHitLand;
// play sounds. // play sounds.
if (soundinfolist.Count > 0) if (soundinfolist.Count > 0)
CollisionSounds.PartCollisionSound(this, soundinfolist); CollisionSounds.PartCollisionSound(this, soundinfolist);
} }
SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); EventManager eventmanager = ParentGroup.Scene.EventManager;
if (!VolumeDetectActive)
SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
if (startedColliders.Contains(0)) SendCollisionEvent(scriptEvents.collision_start, startedColliders, eventmanager.TriggerScriptCollidingStart);
SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart); if (!VolumeDetectActive)
if (m_lastColliders.Contains(0)) SendCollisionEvent(scriptEvents.collision , m_lastColliders , eventmanager.TriggerScriptColliding);
SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); SendCollisionEvent(scriptEvents.collision_end , endedColliders , eventmanager.TriggerScriptCollidingEnd);
if (endedColliders.Contains(0))
SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); if (!VolumeDetectActive)
{
if (startLand)
SendLandCollisionEvent(scriptEvents.land_collision_start, eventmanager.TriggerScriptLandCollidingStart);
if (m_lastLandCollide)
SendLandCollisionEvent(scriptEvents.land_collision, eventmanager.TriggerScriptLandColliding);
if (endedLand)
SendLandCollisionEvent(scriptEvents.land_collision_end, eventmanager.TriggerScriptLandCollidingEnd);
}
} }
// The Collision sounds code calls this // The Collision sounds code calls this
@ -3026,7 +3078,7 @@ namespace OpenSim.Region.Framework.Scenes
//ParentGroup.RootPart.m_groupPosition = newpos; //ParentGroup.RootPart.m_groupPosition = newpos;
} }
/* /*
if (pa != null && ParentID != 0 && ParentGroup != null) if (pa != null && _parentID != 0 && ParentGroup != null)
{ {
// Special case where a child object is requesting property updates. // Special case where a child object is requesting property updates.
// This happens when linksets are modified to use flexible links rather than // This happens when linksets are modified to use flexible links rather than
@ -3236,7 +3288,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Schedule a terse update for this prim. Terse updates only send position, /// Schedule a terse update for this prim. Terse updates only send position,
/// rotation, velocity and rotational velocity information. /// rotation, velocity and rotational velocity information. WRONG!!!!
/// </summary> /// </summary>
public void ScheduleTerseUpdate() public void ScheduleTerseUpdate()
{ {
@ -3295,21 +3347,6 @@ namespace OpenSim.Region.Framework.Scenes
sp.SendAttachmentUpdate(this, UpdateRequired.FULL); sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
} }
} }
/* this does nothing
SendFullUpdateToClient(remoteClient, Position) ignores position parameter
if (IsRoot)
{
if (ParentGroup.IsAttachment)
{
SendFullUpdateToClient(remoteClient, AttachedPos);
}
else
{
SendFullUpdateToClient(remoteClient, AbsolutePosition);
}
}
*/
else else
{ {
SendFullUpdateToClient(remoteClient); SendFullUpdateToClient(remoteClient);
@ -3325,12 +3362,12 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
return; return;
// Update the "last" values // Update the "last" values
m_lastPosition = OffsetPosition; m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset; m_lastRotation = RotationOffset;
m_lastVelocity = Velocity; m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration; m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity; m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount; m_lastUpdateSentTime = Util.GetTimeStampMS();
ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{ {
@ -3344,12 +3381,12 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
return; return;
// Update the "last" values // Update the "last" values
m_lastPosition = OffsetPosition; m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset; m_lastRotation = RotationOffset;
m_lastVelocity = Velocity; m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration; m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity; m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount; m_lastUpdateSentTime = Util.GetTimeStampMS();
if (ParentGroup.IsAttachment) if (ParentGroup.IsAttachment)
{ {
@ -3395,42 +3432,131 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); ParentGroup.Scene.StatsReporter.AddObjectUpdates(1);
} }
private const float ROTATION_TOLERANCE = 0.01f;
private const float VELOCITY_TOLERANCE = 0.1f; // terse update vel has low resolution
private const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
private const double TIME_MS_TOLERANCE = 200f; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
/// <summary> /// <summary>
/// Tell all the prims which have had updates scheduled /// Tell all the prims which have had updates scheduled
/// </summary> /// </summary>
public void SendScheduledUpdates() public void SendScheduledUpdates()
{ {
const float ROTATION_TOLERANCE = 0.01f;
const float VELOCITY_TOLERANCE = 0.001f;
const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
switch (UpdateFlag) switch (UpdateFlag)
{ {
case UpdateRequired.TERSE: case UpdateRequired.NONE:
{
ClearUpdateSchedule(); ClearUpdateSchedule();
// Throw away duplicate or insignificant updates break;
if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
!Acceleration.Equals(m_lastAcceleration) || case UpdateRequired.TERSE:
!Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || ClearUpdateSchedule();
!AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || bool needupdate = true;
!OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || double now = Util.GetTimeStampMS();
Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE) Vector3 curvel = Velocity;
Vector3 curacc = Acceleration;
Vector3 angvel = AngularVelocity;
while(true) // just to avoid ugly goto
{ {
SendTerseUpdateToAllClientsInternal(); double elapsed = now - m_lastUpdateSentTime;
} if (elapsed > TIME_MS_TOLERANCE)
break;
if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE ||
Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE ||
Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE)
break;
// velocity change is also direction not only norm)
if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE)
break;
float vx = Math.Abs(curvel.X);
if(vx > 128.0)
break;
float vy = Math.Abs(curvel.Y);
if(vy > 128.0)
break;
float vz = Math.Abs(curvel.Z);
if(vz > 128.0)
break;
if (
vx < VELOCITY_TOLERANCE &&
vy < VELOCITY_TOLERANCE &&
vz < VELOCITY_TOLERANCE
)
{
if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
break;
if (vx < 1e-4 &&
vy < 1e-4 &&
vz < 1e-4 &&
(
Math.Abs(m_lastVelocity.X) > 1e-4 ||
Math.Abs(m_lastVelocity.Y) > 1e-4 ||
Math.Abs(m_lastVelocity.Z) > 1e-4
))
break; break;
} }
case UpdateRequired.FULL:
if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > VELOCITY_TOLERANCE ||
Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > VELOCITY_TOLERANCE ||
Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > VELOCITY_TOLERANCE)
break;
// viewer interpolators have a limit of 128m/s
float ax = Math.Abs(angvel.X);
if(ax > 64.0)
break;
float ay = Math.Abs(angvel.Y);
if(ay > 64.0)
break;
float az = Math.Abs(angvel.Z);
if(az > 64.0)
break;
if (
ax < VELOCITY_TOLERANCE &&
ay < VELOCITY_TOLERANCE &&
az < VELOCITY_TOLERANCE &&
!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
)
break;
needupdate = false;
break;
}
if(needupdate)
{ {
// Update the "last" values
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = curvel;
m_lastAcceleration = curacc;
m_lastAngularVelocity = angvel;
m_lastUpdateSentTime = now;
ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
{
SendTerseUpdateToClient(client);
});
}
break;
case UpdateRequired.FULL:
ClearUpdateSchedule(); ClearUpdateSchedule();
SendFullUpdateToAllClientsInternal(); SendFullUpdateToAllClientsInternal();
break; break;
} }
} }
}
/// <summary> /// <summary>
@ -3441,13 +3567,15 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
if (ParentGroup == null || ParentGroup.Scene == null) if (ParentGroup == null || ParentGroup.Scene == null)
return; return;
ClearUpdateSchedule();
// Update the "last" values // Update the "last" values
m_lastPosition = OffsetPosition; m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset; m_lastRotation = RotationOffset;
m_lastVelocity = Velocity; m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration; m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity; m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount; m_lastUpdateSentTime = Util.GetTimeStampMS();
ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
{ {
@ -3460,13 +3588,15 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
if (ParentGroup == null || ParentGroup.Scene == null) if (ParentGroup == null || ParentGroup.Scene == null)
return; return;
ClearUpdateSchedule();
// Update the "last" values // Update the "last" values
m_lastPosition = OffsetPosition; m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset; m_lastRotation = RotationOffset;
m_lastVelocity = Velocity; m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration; m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity; m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount; m_lastUpdateSentTime = Util.GetTimeStampMS();
if (ParentGroup.IsAttachment) if (ParentGroup.IsAttachment)
{ {
@ -4783,7 +4913,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
pa.OnOutOfBounds += PhysicsOutOfBounds; pa.OnOutOfBounds += PhysicsOutOfBounds;
if (ParentID != 0 && ParentID != LocalId) if (_parentID != 0 && _parentID != LocalId)
{ {
PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;

View File

@ -279,8 +279,11 @@ namespace OpenSim.Region.Framework.Scenes
private bool MouseDown = false; private bool MouseDown = false;
public Vector3 lastKnownAllowedPosition; public Vector3 lastKnownAllowedPosition;
public bool sentMessageAboutRestrictedParcelFlyingDown; public bool sentMessageAboutRestrictedParcelFlyingDown;
public Vector4 CollisionPlane = Vector4.UnitW; public Vector4 CollisionPlane = Vector4.UnitW;
public Vector4 m_lastCollisionPlane = Vector4.UnitW;
private byte m_lastState;
private Vector3 m_lastPosition; private Vector3 m_lastPosition;
private Quaternion m_lastRotation; private Quaternion m_lastRotation;
private Vector3 m_lastVelocity; private Vector3 m_lastVelocity;
@ -2818,16 +2821,13 @@ namespace OpenSim.Region.Framework.Scenes
CameraAtAxis = agentData.CameraAtAxis; CameraAtAxis = agentData.CameraAtAxis;
CameraLeftAxis = agentData.CameraLeftAxis; CameraLeftAxis = agentData.CameraLeftAxis;
CameraUpAxis = agentData.CameraUpAxis; CameraUpAxis = agentData.CameraUpAxis;
Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis);
CameraRotation = camRot;
// The Agent's Draw distance setting
// When we get to the point of re-computing neighbors everytime this
// changes, then start using the agent's drawdistance rather than the
// region's draw distance.
DrawDistance = agentData.Far; DrawDistance = agentData.Far;
CameraAtAxis.Normalize();
CameraLeftAxis.Normalize();
CameraUpAxis.Normalize();
Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis);
CameraRotation = camRot;
// Check if Client has camera in 'follow cam' or 'build' mode. // Check if Client has camera in 'follow cam' or 'build' mode.
// Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); // Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
@ -3789,23 +3789,13 @@ namespace OpenSim.Region.Framework.Scenes
// Send terse position update if not sitting and position, velocity, or rotation // Send terse position update if not sitting and position, velocity, or rotation
// has changed significantly from last sent update // has changed significantly from last sent update
if (!IsSatOnObject && (
!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
|| !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE)
|| !m_pos.ApproxEquals(m_lastPosition, POSITION_LARGETOLERANCE)
// if velocity is zero and it wasn't zero last time, send the update
|| (Velocity == Vector3.Zero && m_lastVelocity != Vector3.Zero)
// if position has moved just a little and velocity is very low, send the update
|| (!m_pos.ApproxEquals(m_lastPosition, POSITION_SMALLTOLERANCE) && Velocity.LengthSquared() < LOWVELOCITYSQ )
) )
{
/*
if (!IsSatOnObject) if (!IsSatOnObject)
{ {
// this does need to be more complex later // this does need to be more complex later
Vector3 vel = Velocity; Vector3 vel = Velocity;
Vector3 dpos = m_pos - m_lastPosition; Vector3 dpos = m_pos - m_lastPosition;
if( Math.Abs(vel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || if( State != m_lastState ||
Math.Abs(vel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
Math.Abs(vel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE || Math.Abs(vel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
Math.Abs(vel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE || Math.Abs(vel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE ||
@ -3813,6 +3803,8 @@ namespace OpenSim.Region.Framework.Scenes
Math.Abs(m_bodyRot.Y - m_lastRotation.Y) > ROTATION_TOLERANCE || Math.Abs(m_bodyRot.Y - m_lastRotation.Y) > ROTATION_TOLERANCE ||
Math.Abs(m_bodyRot.Z - m_lastRotation.Z) > ROTATION_TOLERANCE || Math.Abs(m_bodyRot.Z - m_lastRotation.Z) > ROTATION_TOLERANCE ||
(vel == Vector3.Zero && m_lastVelocity != Vector3.Zero) ||
Math.Abs(dpos.X) > POSITION_LARGETOLERANCE || Math.Abs(dpos.X) > POSITION_LARGETOLERANCE ||
Math.Abs(dpos.Y) > POSITION_LARGETOLERANCE || Math.Abs(dpos.Y) > POSITION_LARGETOLERANCE ||
Math.Abs(dpos.Z) > POSITION_LARGETOLERANCE || Math.Abs(dpos.Z) > POSITION_LARGETOLERANCE ||
@ -3821,11 +3813,15 @@ namespace OpenSim.Region.Framework.Scenes
Math.Abs(dpos.Y) > POSITION_SMALLTOLERANCE || Math.Abs(dpos.Y) > POSITION_SMALLTOLERANCE ||
Math.Abs(dpos.Z) > POSITION_SMALLTOLERANCE) Math.Abs(dpos.Z) > POSITION_SMALLTOLERANCE)
&& vel.LengthSquared() < LOWVELOCITYSQ && vel.LengthSquared() < LOWVELOCITYSQ
)) ) ||
Math.Abs(CollisionPlane.X - m_lastCollisionPlane.X) > POSITION_SMALLTOLERANCE ||
Math.Abs(CollisionPlane.Y - m_lastCollisionPlane.Y) > POSITION_SMALLTOLERANCE ||
Math.Abs(CollisionPlane.W - m_lastCollisionPlane.W) > POSITION_SMALLTOLERANCE
)
{ {
*/
SendTerseUpdateToAllClients(); SendTerseUpdateToAllClients();
// } }
} }
CheckForSignificantMovement(); CheckForSignificantMovement();
} }
@ -3921,11 +3917,14 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void SendTerseUpdateToAllClients() public void SendTerseUpdateToAllClients()
{ {
m_scene.ForEachScenePresence(SendTerseUpdateToAgent); m_lastState = State;
// Update the "last" values
m_lastPosition = m_pos; m_lastPosition = m_pos;
m_lastRotation = m_bodyRot; m_lastRotation = m_bodyRot;
m_lastVelocity = Velocity; m_lastVelocity = Velocity;
m_lastCollisionPlane = CollisionPlane;
m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
// Update the "last" values
TriggerScenePresenceUpdated(); TriggerScenePresenceUpdated();
} }

View File

@ -86,9 +86,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteStartElement("CoalescedObject"); writer.WriteStartElement("CoalescedObject");
writer.WriteAttributeString("x", size.X.ToString()); writer.WriteAttributeString("x", size.X.ToString(Culture.FormatProvider));
writer.WriteAttributeString("y", size.Y.ToString()); writer.WriteAttributeString("y", size.Y.ToString(Culture.FormatProvider));
writer.WriteAttributeString("z", size.Z.ToString()); writer.WriteAttributeString("z", size.Z.ToString(Culture.FormatProvider));
// Embed the offsets into the group XML // Embed the offsets into the group XML
for (int i = 0; i < coaObjects.Count; i++) for (int i = 0; i < coaObjects.Count; i++)
@ -100,9 +100,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
// i, obj.Name); // i, obj.Name);
writer.WriteStartElement("SceneObjectGroup"); writer.WriteStartElement("SceneObjectGroup");
writer.WriteAttributeString("offsetx", offsets[i].X.ToString()); writer.WriteAttributeString("offsetx", offsets[i].X.ToString(Culture.FormatProvider));
writer.WriteAttributeString("offsety", offsets[i].Y.ToString()); writer.WriteAttributeString("offsety", offsets[i].Y.ToString(Culture.FormatProvider));
writer.WriteAttributeString("offsetz", offsets[i].Z.ToString()); writer.WriteAttributeString("offsetz", offsets[i].Z.ToString(Culture.FormatProvider));
SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, doScriptStates); SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, doScriptStates);

View File

@ -65,7 +65,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
{ {
using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment }))
{ {
try { try
{
return FromOriginalXmlFormat(reader); return FromOriginalXmlFormat(reader);
} }
catch (Exception e) catch (Exception e)
@ -109,11 +110,23 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
} }
} }
while (reader.ReadToNextSibling("Part")); while (reader.ReadToNextSibling("Part"));
reader.ReadEndElement();
} }
if (reader.Name == "KeyframeMotion" && reader.NodeType == XmlNodeType.Element)
{
string innerkeytxt = reader.ReadElementContentAsString();
sceneObject.RootPart.KeyframeMotion =
KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(innerkeytxt));
}
else
sceneObject.RootPart.KeyframeMotion = null;
// Script state may, or may not, exist. Not having any, is NOT // Script state may, or may not, exist. Not having any, is NOT
// ever a problem. // ever a problem.
sceneObject.LoadScriptState(reader); sceneObject.LoadScriptState(reader);
sceneObject.InvalidateDeepEffectivePerms(); sceneObject.InvalidateDeepEffectivePerms();
return sceneObject; return sceneObject;
} }
@ -210,9 +223,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteEndElement(); // OtherParts writer.WriteEndElement(); // OtherParts
if (sceneObject.RootPart.KeyframeMotion != null)
{
Byte[] data = sceneObject.RootPart.KeyframeMotion.Serialize();
writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
writer.WriteBase64(data, 0, data.Length);
writer.WriteEndElement();
}
if (doScriptStates) if (doScriptStates)
sceneObject.SaveScriptedState(writer); sceneObject.SaveScriptedState(writer);
if (!noRootElement) if (!noRootElement)
writer.WriteEndElement(); // SceneObjectGroup writer.WriteEndElement(); // SceneObjectGroup
@ -1459,10 +1482,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("Description", sop.Description); writer.WriteElementString("Description", sop.Description);
writer.WriteStartElement("Color"); writer.WriteStartElement("Color");
writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture)); writer.WriteElementString("R", sop.Color.R.ToString(Culture.FormatProvider));
writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture)); writer.WriteElementString("G", sop.Color.G.ToString(Culture.FormatProvider));
writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture)); writer.WriteElementString("B", sop.Color.B.ToString(Culture.FormatProvider));
writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture)); writer.WriteElementString("A", sop.Color.A.ToString(Culture.FormatProvider));
writer.WriteEndElement(); writer.WriteEndElement();
writer.WriteElementString("Text", sop.Text); writer.WriteElementString("Text", sop.Text);
@ -1505,7 +1528,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("NextOwnerMask", sop.NextOwnerMask.ToString()); writer.WriteElementString("NextOwnerMask", sop.NextOwnerMask.ToString());
WriteFlags(writer, "Flags", sop.Flags.ToString(), options); WriteFlags(writer, "Flags", sop.Flags.ToString(), options);
WriteUUID(writer, "CollisionSound", sop.CollisionSound, options); WriteUUID(writer, "CollisionSound", sop.CollisionSound, options);
writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString(Culture.FormatProvider));
if (sop.MediaUrl != null) if (sop.MediaUrl != null)
writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
WriteVector(writer, "AttachedPos", sop.AttachedPos); WriteVector(writer, "AttachedPos", sop.AttachedPos);
@ -1525,7 +1548,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString()); writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString(Culture.FormatProvider));
WriteVector(writer, "Force", sop.Force); WriteVector(writer, "Force", sop.Force);
WriteVector(writer, "Torque", sop.Torque); WriteVector(writer, "Torque", sop.Torque);
@ -1542,22 +1565,22 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("RotationAxisLocks", sop.RotationAxisLocks.ToString().ToLower()); writer.WriteElementString("RotationAxisLocks", sop.RotationAxisLocks.ToString().ToLower());
writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
if (sop.Density != 1000.0f) if (sop.Density != 1000.0f)
writer.WriteElementString("Density", sop.Density.ToString().ToLower()); writer.WriteElementString("Density", sop.Density.ToString(Culture.FormatProvider));
if (sop.Friction != 0.6f) if (sop.Friction != 0.6f)
writer.WriteElementString("Friction", sop.Friction.ToString().ToLower()); writer.WriteElementString("Friction", sop.Friction.ToString(Culture.FormatProvider));
if (sop.Restitution != 0.5f) if (sop.Restitution != 0.5f)
writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower()); writer.WriteElementString("Bounce", sop.Restitution.ToString(Culture.FormatProvider));
if (sop.GravityModifier != 1.0f) if (sop.GravityModifier != 1.0f)
writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString(Culture.FormatProvider));
WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset()); WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
// if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
{ {
WriteUUID(writer, "SoundID", sop.Sound, options); WriteUUID(writer, "SoundID", sop.Sound, options);
writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower()); writer.WriteElementString("SoundGain", sop.SoundGain.ToString(Culture.FormatProvider));
writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower()); writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower()); writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString(Culture.FormatProvider));
} }
writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower()); writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
@ -1577,19 +1600,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
static void WriteVector(XmlTextWriter writer, string name, Vector3 vec) static void WriteVector(XmlTextWriter writer, string name, Vector3 vec)
{ {
writer.WriteStartElement(name); writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture)); writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture)); writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture)); writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
writer.WriteEndElement(); writer.WriteEndElement();
} }
static void WriteQuaternion(XmlTextWriter writer, string name, Quaternion quat) static void WriteQuaternion(XmlTextWriter writer, string name, Quaternion quat)
{ {
writer.WriteStartElement(name); writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture)); writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture)); writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture)); writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture)); writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
writer.WriteEndElement(); writer.WriteEndElement();
} }
@ -1731,22 +1754,22 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
// Don't serialize SculptData. It's just a copy of the asset, which can be loaded separately using 'SculptTexture'. // Don't serialize SculptData. It's just a copy of the asset, which can be loaded separately using 'SculptTexture'.
writer.WriteElementString("FlexiSoftness", shp.FlexiSoftness.ToString()); writer.WriteElementString("FlexiSoftness", shp.FlexiSoftness.ToString());
writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString()); writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString()); writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString()); writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString()); writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString()); writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString()); writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString()); writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorR", shp.LightColorR.ToString()); writer.WriteElementString("LightColorR", shp.LightColorR.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorG", shp.LightColorG.ToString()); writer.WriteElementString("LightColorG", shp.LightColorG.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorB", shp.LightColorB.ToString()); writer.WriteElementString("LightColorB", shp.LightColorB.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorA", shp.LightColorA.ToString()); writer.WriteElementString("LightColorA", shp.LightColorA.ToString(Culture.FormatProvider));
writer.WriteElementString("LightRadius", shp.LightRadius.ToString()); writer.WriteElementString("LightRadius", shp.LightRadius.ToString(Culture.FormatProvider));
writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString()); writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString(Culture.FormatProvider));
writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString()); writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString(Culture.FormatProvider));
writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString()); writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiEntry", shp.FlexiEntry.ToString().ToLower()); writer.WriteElementString("FlexiEntry", shp.FlexiEntry.ToString().ToLower());
writer.WriteElementString("LightEntry", shp.LightEntry.ToString().ToLower()); writer.WriteElementString("LightEntry", shp.LightEntry.ToString().ToLower());

View File

@ -54,8 +54,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
UUID ownerId = TestHelpers.ParseTail(0x1); UUID ownerId = TestHelpers.ParseTail(0x1);
SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10); SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10);
so1.ScriptSetPhysicsStatus(true);
m_scene.AddSceneObject(so1); m_scene.AddSceneObject(so1);
so1.ScriptSetPhysicsStatus(true);
Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3)); Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3));
Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3)); Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3));

View File

@ -65,7 +65,10 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
/// <value>The gathered uuids.</value> /// <value>The gathered uuids.</value>
public IDictionary<UUID, sbyte> GatheredUuids { get; private set; } public IDictionary<UUID, sbyte> GatheredUuids { get; private set; }
public HashSet<UUID> FailedUUIDs { get; private set; }
public HashSet<UUID> UncertainAssetsUUIDs { get; private set; }
public int possibleNotAssetCount { get; set; }
public int ErrorCount { get; private set; }
/// <summary> /// <summary>
/// Gets the next UUID to inspect. /// Gets the next UUID to inspect.
/// </summary> /// </summary>
@ -92,7 +95,10 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="assetService"> /// <param name="assetService">
/// Asset service. /// Asset service.
/// </param> /// </param>
public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary<UUID, sbyte>()) {} public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary<UUID, sbyte>(),
new HashSet <UUID>(),new HashSet <UUID>()) {}
public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector) : this(assetService, collector,
new HashSet <UUID>(), new HashSet <UUID>()) {}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class. /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class.
@ -101,16 +107,20 @@ namespace OpenSim.Region.Framework.Scenes
/// Asset service. /// Asset service.
/// </param> /// </param>
/// <param name="collector"> /// <param name="collector">
/// Gathered UUIDs will be collected in this dictinaory. /// Gathered UUIDs will be collected in this dictionary.
/// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected. /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected.
/// </param> /// </param>
public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector) public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector, HashSet <UUID> failedIDs, HashSet <UUID> uncertainAssetsUUIDs)
{ {
m_assetService = assetService; m_assetService = assetService;
GatheredUuids = collector; GatheredUuids = collector;
// FIXME: Not efficient for searching, can improve. // FIXME: Not efficient for searching, can improve.
m_assetUuidsToInspect = new Queue<UUID>(); m_assetUuidsToInspect = new Queue<UUID>();
FailedUUIDs = failedIDs;
UncertainAssetsUUIDs = uncertainAssetsUUIDs;
ErrorCount = 0;
possibleNotAssetCount = 0;
} }
/// <summary> /// <summary>
@ -120,6 +130,19 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="uuid">UUID.</param> /// <param name="uuid">UUID.</param>
public bool AddForInspection(UUID uuid) public bool AddForInspection(UUID uuid)
{ {
if(uuid == UUID.Zero)
return false;
if(FailedUUIDs.Contains(uuid))
{
if(UncertainAssetsUUIDs.Contains(uuid))
possibleNotAssetCount++;
else
ErrorCount++;
return false;
}
if(GatheredUuids.ContainsKey(uuid))
return false;
if (m_assetUuidsToInspect.Contains(uuid)) if (m_assetUuidsToInspect.Contains(uuid))
return false; return false;
@ -141,7 +164,9 @@ namespace OpenSim.Region.Framework.Scenes
public void AddForInspection(SceneObjectGroup sceneObject) public void AddForInspection(SceneObjectGroup sceneObject)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); // "[UUID GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
if(sceneObject.IsDeleted)
return;
SceneObjectPart[] parts = sceneObject.Parts; SceneObjectPart[] parts = sceneObject.Parts;
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
@ -149,7 +174,7 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart part = parts[i]; SceneObjectPart part = parts[i];
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); // "[UUID GATHERER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
try try
{ {
@ -207,8 +232,6 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}",
// tii.Name, tii.Type, part.Name, part.UUID); // tii.Name, tii.Type, part.Name, part.UUID);
if (!GatheredUuids.ContainsKey(tii.AssetID))
AddForInspection(tii.AssetID, (sbyte)tii.Type); AddForInspection(tii.AssetID, (sbyte)tii.Type);
} }
@ -225,9 +248,6 @@ namespace OpenSim.Region.Framework.Scenes
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e);
m_log.DebugFormat(
"[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)",
part.Shape.TextureEntry.Length);
} }
} }
} }
@ -278,19 +298,62 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
private void GetAssetUuids(UUID assetUuid) private void GetAssetUuids(UUID assetUuid)
{ {
if(assetUuid == UUID.Zero)
return;
if(FailedUUIDs.Contains(assetUuid))
{
if(UncertainAssetsUUIDs.Contains(assetUuid))
possibleNotAssetCount++;
else
ErrorCount++;
return;
}
// avoid infinite loops // avoid infinite loops
if (GatheredUuids.ContainsKey(assetUuid)) if (GatheredUuids.ContainsKey(assetUuid))
return; return;
AssetBase assetBase;
try try
{ {
AssetBase assetBase = GetAsset(assetUuid); assetBase = GetAsset(assetUuid);
}
if (null != assetBase) catch (Exception e)
{ {
sbyte assetType = assetBase.Type; m_log.ErrorFormat("[UUID GATHERER]: Failed to get asset {0} : {1}", assetUuid, e.Message);
GatheredUuids[assetUuid] = assetType; ErrorCount++;
FailedUUIDs.Add(assetUuid);
return;
}
if(assetBase == null)
{
// m_log.ErrorFormat("[UUID GATHERER]: asset {0} not found", assetUuid);
FailedUUIDs.Add(assetUuid);
if(UncertainAssetsUUIDs.Contains(assetUuid))
possibleNotAssetCount++;
else
ErrorCount++;
return;
}
if(UncertainAssetsUUIDs.Contains(assetUuid))
UncertainAssetsUUIDs.Remove(assetUuid);
sbyte assetType = assetBase.Type;
if(assetBase.Data == null || assetBase.Data.Length == 0)
{
// m_log.ErrorFormat("[UUID GATHERER]: asset {0}, type {1} has no data", assetUuid, assetType);
ErrorCount++;
FailedUUIDs.Add(assetUuid);
return;
}
GatheredUuids[assetUuid] = assetType;
try
{
if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
{ {
RecordWearableAssetUuids(assetBase); RecordWearableAssetUuids(assetBase);
@ -316,17 +379,31 @@ namespace OpenSim.Region.Framework.Scenes
RecordSceneObjectAssetUuids(assetBase); RecordSceneObjectAssetUuids(assetBase);
} }
} }
} catch (Exception e)
catch (Exception)
{ {
m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset id {0}", assetUuid); m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset with id {0} type {1}: {2}", assetUuid, assetType, e.Message);
throw; GatheredUuids.Remove(assetUuid);
ErrorCount++;
FailedUUIDs.Add(assetUuid);
} }
} }
private void AddForInspection(UUID assetUuid, sbyte assetType) private void AddForInspection(UUID assetUuid, sbyte assetType)
{ {
if(assetUuid == UUID.Zero)
return;
// Here, we want to collect uuids which require further asset fetches but mark the others as gathered // Here, we want to collect uuids which require further asset fetches but mark the others as gathered
if(FailedUUIDs.Contains(assetUuid))
{
if(UncertainAssetsUUIDs.Contains(assetUuid))
possibleNotAssetCount++;
else
ErrorCount++;
return;
}
if(GatheredUuids.ContainsKey(assetUuid))
return;
try try
{ {
if ((sbyte)AssetType.Bodypart == assetType if ((sbyte)AssetType.Bodypart == assetType
@ -458,8 +535,11 @@ namespace OpenSim.Region.Framework.Scenes
foreach (Match uuidMatch in uuidMatches) foreach (Match uuidMatch in uuidMatches)
{ {
UUID uuid = new UUID(uuidMatch.Value); UUID uuid = new UUID(uuidMatch.Value);
if(uuid == UUID.Zero)
continue;
// m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid); // m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid);
if(!UncertainAssetsUUIDs.Contains(uuid))
UncertainAssetsUUIDs.Add(uuid);
AddForInspection(uuid); AddForInspection(uuid);
} }
} }

View File

@ -59,23 +59,23 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Config Settings Documentation. /// Config Settings Documentation.
/// Each configuration setting can be specified in two places: OpenSim.ini or Regions.ini. /// Configuration setting can be specified in two places: OpenSim.ini and/or Regions.ini.
/// If specified in Regions.ini, the settings should be within the region's section name.
/// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section.
/// Region-specific settings take precedence.
/// ///
/// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis. /// OpenSim.ini only settings section [AutoBackupModule]
/// All other settings under [AutoBackupModule] are ignored if AutoBackupModuleEnabled is false, even per-region settings! /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module.
/// AutoBackup: True/False. Default: False. If True, activate auto backup functionality. /// if false module is disable and all rest is ignored
/// This is the only required option for enabling auto-backup; the other options have sane defaults.
/// If False for a particular region, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored.
/// If False globally (the default), only regions that specifically override it in Regions.ini will get AutoBackup functionality.
/// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours). /// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours).
/// The number of minutes between each backup attempt. /// The number of minutes between each backup attempt.
/// If a negative or zero value is given, it is equivalent to setting AutoBackup = False. /// AutoBackupDir: String. Default: "." (the current directory).
/// AutoBackupBusyCheck: True/False. Default: True. /// A directory (absolute or relative) where backups should be saved.
/// If True, we will only take an auto-backup if a set of conditions are met. /// AutoBackupKeepFilesForDays remove files older than this number of days. 0 disables
/// These conditions are heuristics to try and avoid taking a backup when the sim is busy. ///
/// Next can be set on OpenSim.ini, as default, and or per region in Regions.ini
/// Region-specific settings take precedence.
///
/// AutoBackup: True/False. Default: False. If True, activate auto backup functionality.
/// controls backup per region, with default optionaly set on OpenSim.ini
/// AutoBackupSkipAssets /// AutoBackupSkipAssets
/// If true, assets are not saved to the oar file. Considerably reduces impact on simulator when backing up. Intended for when assets db is backed up separately /// If true, assets are not saved to the oar file. Considerably reduces impact on simulator when backing up. Intended for when assets db is backed up separately
/// AutoBackupKeepFilesForDays /// AutoBackupKeepFilesForDays
@ -91,38 +91,26 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// "Time": Current timestamp is appended to file name. An existing file will never be overwritten. /// "Time": Current timestamp is appended to file name. An existing file will never be overwritten.
/// "Sequential": A number is appended to the file name. So if RegionName_x.oar exists, we'll save to RegionName_{x+1}.oar next. An existing file will never be overwritten. /// "Sequential": A number is appended to the file name. So if RegionName_x.oar exists, we'll save to RegionName_{x+1}.oar next. An existing file will never be overwritten.
/// "Overwrite": Always save to file named "${AutoBackupDir}/RegionName.oar", even if we have to overwrite an existing file. /// "Overwrite": Always save to file named "${AutoBackupDir}/RegionName.oar", even if we have to overwrite an existing file.
/// AutoBackupDir: String. Default: "." (the current directory).
/// A directory (absolute or relative) where backups should be saved.
/// AutoBackupDilationThreshold: float. Default: 0.5. Lower bound on time dilation required for BusyCheck heuristics to pass.
/// If the time dilation is below this value, don't take a backup right now.
/// AutoBackupAgentThreshold: int. Default: 10. Upper bound on # of agents in region required for BusyCheck heuristics to pass.
/// If the number of agents is greater than this value, don't take a backup right now
/// Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions.
/// Also helps if you don't want AutoBackup at all.
/// </remarks> /// </remarks>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AutoBackupModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AutoBackupModule")]
public class AutoBackupModule : ISharedRegionModule public class AutoBackupModule : ISharedRegionModule
{ {
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly Dictionary<Guid, IScene> m_pendingSaves = new Dictionary<Guid, IScene>(1);
private readonly AutoBackupModuleState m_defaultState = new AutoBackupModuleState(); private readonly AutoBackupModuleState m_defaultState = new AutoBackupModuleState();
private readonly Dictionary<IScene, AutoBackupModuleState> m_states = private readonly Dictionary<IScene, AutoBackupModuleState> m_states =
new Dictionary<IScene, AutoBackupModuleState>(1); new Dictionary<IScene, AutoBackupModuleState>(1);
private readonly Dictionary<Timer, List<IScene>> m_timerMap =
new Dictionary<Timer, List<IScene>>(1);
private readonly Dictionary<double, Timer> m_timers = new Dictionary<double, Timer>(1);
private delegate T DefaultGetter<T>(string settingName, T defaultValue); private delegate T DefaultGetter<T>(string settingName, T defaultValue);
private bool m_enabled; private bool m_enabled;
private ICommandConsole m_console; private ICommandConsole m_console;
private List<Scene> m_Scenes = new List<Scene> (); private List<Scene> m_Scenes = new List<Scene> ();
private Timer m_masterTimer;
private bool m_busy;
/// <summary> private int m_KeepFilesForDays = -1;
/// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState! private string m_backupDir;
/// </summary> private bool m_doneFirst;
private bool m_closed; private double m_baseInterval;
private IConfigSource m_configSource; private IConfigSource m_configSource;
@ -159,36 +147,38 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
void IRegionModuleBase.Initialise(IConfigSource source) void IRegionModuleBase.Initialise(IConfigSource source)
{ {
// Determine if we have been enabled at all in OpenSim.ini -- this is part and parcel of being an optional module // Determine if we have been enabled at all in OpenSim.ini -- this is part and parcel of being an optional module
this.m_configSource = source; m_configSource = source;
IConfig moduleConfig = source.Configs["AutoBackupModule"]; IConfig moduleConfig = source.Configs["AutoBackupModule"];
if (moduleConfig == null) if (moduleConfig == null)
{ {
this.m_enabled = false; m_enabled = false;
return; return;
} }
else
{ m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false);
this.m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false); if(!m_enabled)
if (this.m_enabled) return;
{
ParseDefaultConfig(moduleConfig);
if(!m_enabled)
return;
m_log.Debug("[AUTO BACKUP]: Default config:");
m_log.Debug(m_defaultState.ToString());
m_log.Info("[AUTO BACKUP]: AutoBackupModule enabled"); m_log.Info("[AUTO BACKUP]: AutoBackupModule enabled");
} m_masterTimer = new Timer();
else m_masterTimer.Interval = m_baseInterval;
{ m_masterTimer.Elapsed += HandleElapsed;
return; m_masterTimer.AutoReset = false;
}
}
Timer defTimer = new Timer(43200000); m_console = MainConsole.Instance;
this.m_defaultState.Timer = defTimer;
this.m_timers.Add(43200000, defTimer);
defTimer.Elapsed += this.HandleElapsed;
defTimer.AutoReset = true;
defTimer.Start();
AutoBackupModuleState abms = this.ParseConfig(null, true); m_console.Commands.AddCommand (
m_log.Debug("[AUTO BACKUP]: Here is the default config:"); "AutoBackup", true, "dooarbackup",
m_log.Debug(abms.ToString()); "dooarbackup <regionName> | ALL",
"saves the single region <regionName> to a oar or ALL regions in instance to oars, using same settings as AutoBackup. Note it restarts time interval", DoBackup);
m_busy = true;
} }
/// <summary> /// <summary>
@ -196,13 +186,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// </summary> /// </summary>
void IRegionModuleBase.Close() void IRegionModuleBase.Close()
{ {
if (!this.m_enabled) if (!m_enabled)
{
return; return;
}
// We don't want any timers firing while the sim's coming down; strange things may happen. // We don't want any timers firing while the sim's coming down; strange things may happen.
this.StopAllTimers(); m_masterTimer.Dispose();
} }
/// <summary> /// <summary>
@ -211,18 +199,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="scene"></param> /// <param name="scene"></param>
void IRegionModuleBase.AddRegion (Scene scene) void IRegionModuleBase.AddRegion (Scene scene)
{ {
if (!this.m_enabled) { if (!m_enabled)
return; return;
}
lock (m_Scenes) {
m_Scenes.Add (scene);
}
m_console = MainConsole.Instance;
m_console.Commands.AddCommand ( lock (m_Scenes)
"AutoBackup", false, "dobackup", m_Scenes.Add (scene);
"dobackup",
"do backup.", DoBackup);
} }
/// <summary> /// <summary>
@ -231,28 +212,14 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="scene">The scene (region) to stop performing AutoBackup on.</param> /// <param name="scene">The scene (region) to stop performing AutoBackup on.</param>
void IRegionModuleBase.RemoveRegion(Scene scene) void IRegionModuleBase.RemoveRegion(Scene scene)
{ {
if (!this.m_enabled) if (m_enabled)
{
return; return;
}
lock(m_Scenes)
{
if (m_states.ContainsKey(scene))
m_states.Remove(scene);
m_Scenes.Remove(scene); m_Scenes.Remove(scene);
if (this.m_states.ContainsKey(scene))
{
AutoBackupModuleState abms = this.m_states[scene];
// Remove this scene out of the timer map list
Timer timer = abms.Timer;
List<IScene> list = this.m_timerMap[timer];
list.Remove(scene);
// Shut down the timer if this was the last scene for the timer
if (list.Count == 0)
{
this.m_timerMap.Remove(timer);
this.m_timers.Remove(timer.Interval);
timer.Close();
}
this.m_states.Remove(scene);
} }
} }
@ -263,22 +230,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="scene">The scene to (possibly) perform AutoBackup on.</param> /// <param name="scene">The scene to (possibly) perform AutoBackup on.</param>
void IRegionModuleBase.RegionLoaded(Scene scene) void IRegionModuleBase.RegionLoaded(Scene scene)
{ {
if (!this.m_enabled) if (!m_enabled)
{
return; return;
}
// This really ought not to happen, but just in case, let's pretend it didn't... // This really ought not to happen, but just in case, let's pretend it didn't...
if (scene == null) if (scene == null)
{
return; return;
AutoBackupModuleState abms = ParseConfig(scene);
if(abms == null)
{
m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
m_log.Debug("DEFAULT");
abms = new AutoBackupModuleState(m_defaultState);
}
else
{
m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
m_log.Debug(abms.ToString());
} }
AutoBackupModuleState abms = this.ParseConfig(scene, false);
m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
m_log.Debug((abms == null ? "DEFAULT" : abms.ToString()));
m_states.Add(scene, abms); m_states.Add(scene, abms);
m_busy = false;
m_masterTimer.Start();
} }
/// <summary> /// <summary>
@ -292,24 +266,122 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
private void DoBackup (string module, string[] args) private void DoBackup (string module, string[] args)
{ {
if (args.Length != 2) { if (!m_enabled)
MainConsole.Instance.OutputFormat ("Usage: dobackup <regionname>"); return;
if (args.Length != 2)
{
MainConsole.Instance.OutputFormat ("Usage: dooarbackup <regionname>");
return; return;
} }
if(m_busy)
{
MainConsole.Instance.OutputFormat ("Already doing a backup, please try later");
return;
}
m_masterTimer.Stop();
m_busy = true;
bool found = false; bool found = false;
string name = args [1]; string name = args [1];
lock (m_Scenes) { Scene[] scenes;
foreach (Scene s in m_Scenes) { lock (m_Scenes)
string test = s.Name.ToString (); scenes = m_Scenes.ToArray();
if (test == name) {
if(scenes == null)
return;
Scene s;
try
{
if(name == "ALL")
{
for(int i = 0; i < scenes.Length; i++)
{
s = scenes[i];
DoRegionBackup(s);
if (!m_enabled)
return;
}
return;
}
for(int i = 0; i < scenes.Length; i++)
{
s = scenes[i];
if (s.Name == name)
{
found = true; found = true;
DoRegionBackup(s); DoRegionBackup(s);
break;
} }
} }
if (!found) { }
catch { }
finally
{
if (m_enabled)
m_masterTimer.Start();
m_busy = false;
}
if (!found)
MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name); MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name);
} }
private void ParseDefaultConfig(IConfig config)
{
m_backupDir = ".";
string backupDir = config.GetString("AutoBackupDir", ".");
if (backupDir != ".")
{
try
{
DirectoryInfo dirinfo = new DirectoryInfo(backupDir);
if (!dirinfo.Exists)
dirinfo.Create();
} }
catch (Exception e)
{
m_enabled = false;
m_log.WarnFormat("[AUTO BACKUP]: Error accessing backup folder {0}. Module disabled. {1}",
backupDir, e);
return;
}
}
m_backupDir = backupDir;
double interval = config.GetDouble("AutoBackupInterval", 720);
interval *= 60000.0;
m_baseInterval = interval;
// How long to keep backup files in days, 0 Disables this feature
m_KeepFilesForDays = config.GetInt("AutoBackupKeepFilesForDays",m_KeepFilesForDays);
m_defaultState.Enabled = config.GetBoolean("AutoBackup", m_defaultState.Enabled);
m_defaultState.SkipAssets = config.GetBoolean("AutoBackupSkipAssets",m_defaultState.SkipAssets);
// Set file naming algorithm
string stmpNamingType = config.GetString("AutoBackupNaming", m_defaultState.NamingType.ToString());
NamingType tmpNamingType;
if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase))
tmpNamingType = NamingType.Time;
else if (stmpNamingType.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase))
tmpNamingType = NamingType.Sequential;
else if (stmpNamingType.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase))
tmpNamingType = NamingType.Overwrite;
else
{
m_log.Warn("Unknown naming type specified for Default");
tmpNamingType = NamingType.Time;
}
m_defaultState.NamingType = tmpNamingType;
m_defaultState.Script = config.GetString("AutoBackupScript", m_defaultState.Script);
} }
/// <summary> /// <summary>
@ -319,329 +391,49 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="scene">The scene to look at.</param> /// <param name="scene">The scene to look at.</param>
/// <param name="parseDefault">Whether this call is intended to figure out what we consider the "default" config (applied to all regions unless overridden by per-region settings).</param> /// <param name="parseDefault">Whether this call is intended to figure out what we consider the "default" config (applied to all regions unless overridden by per-region settings).</param>
/// <returns>An AutoBackupModuleState contains most information you should need to know relevant to auto-backup, as applicable to a single region.</returns> /// <returns>An AutoBackupModuleState contains most information you should need to know relevant to auto-backup, as applicable to a single region.</returns>
private AutoBackupModuleState ParseConfig(IScene scene, bool parseDefault) private AutoBackupModuleState ParseConfig(IScene scene)
{ {
string sRegionName; if(scene == null)
string sRegionLabel; return null;
// string prepend;
AutoBackupModuleState state; string sRegionName;
AutoBackupModuleState state = null;
if (parseDefault)
{
sRegionName = null;
sRegionLabel = "DEFAULT";
// prepend = "";
state = this.m_defaultState;
}
else
{
sRegionName = scene.RegionInfo.RegionName; sRegionName = scene.RegionInfo.RegionName;
sRegionLabel = sRegionName;
// prepend = sRegionName + ".";
state = null;
}
// Read the config settings and set variables. // Read the config settings and set variables.
IConfig regionConfig = (scene != null ? scene.Config.Configs[sRegionName] : null); IConfig regionConfig = scene.Config.Configs[sRegionName];
IConfig config = this.m_configSource.Configs["AutoBackupModule"]; if (regionConfig == null)
if (config == null) return null;
{
// defaultState would be disabled too if the section doesn't exist.
state = this.m_defaultState;
return state;
}
bool tmpEnabled = ResolveBoolean("AutoBackup", this.m_defaultState.Enabled, config, regionConfig);
if (state == null && tmpEnabled != this.m_defaultState.Enabled)
//Varies from default state
{
state = new AutoBackupModuleState(); state = new AutoBackupModuleState();
}
if (state != null) state.Enabled = regionConfig.GetBoolean("AutoBackup", m_defaultState.Enabled);
{
state.Enabled = tmpEnabled;
}
// If you don't want AutoBackup, we stop.
if ((state == null && !this.m_defaultState.Enabled) || (state != null && !state.Enabled))
{
return state;
}
else
{
m_log.Info("[AUTO BACKUP]: Region " + sRegionLabel + " is AutoBackup ENABLED.");
}
// Borrow an existing timer if one exists for the same interval; otherwise, make a new one.
double interval =
this.ResolveDouble("AutoBackupInterval", this.m_defaultState.IntervalMinutes,
config, regionConfig) * 60000.0;
if (state == null && interval != this.m_defaultState.IntervalMinutes * 60000.0)
{
state = new AutoBackupModuleState();
}
if (this.m_timers.ContainsKey(interval))
{
if (state != null)
{
state.Timer = this.m_timers[interval];
}
m_log.Debug("[AUTO BACKUP]: Reusing timer for " + interval + " msec for region " +
sRegionLabel);
}
else
{
// 0 or negative interval == do nothing.
if (interval <= 0.0 && state != null)
{
state.Enabled = false;
return state;
}
if (state == null)
{
state = new AutoBackupModuleState();
}
Timer tim = new Timer(interval);
state.Timer = tim;
//Milliseconds -> minutes
this.m_timers.Add(interval, tim);
tim.Elapsed += this.HandleElapsed;
tim.AutoReset = true;
tim.Start();
}
// Add the current region to the list of regions tied to this timer.
if (scene != null)
{
if (state != null)
{
if (this.m_timerMap.ContainsKey(state.Timer))
{
this.m_timerMap[state.Timer].Add(scene);
}
else
{
List<IScene> scns = new List<IScene>(1);
scns.Add(scene);
this.m_timerMap.Add(state.Timer, scns);
}
}
else
{
if (this.m_timerMap.ContainsKey(this.m_defaultState.Timer))
{
this.m_timerMap[this.m_defaultState.Timer].Add(scene);
}
else
{
List<IScene> scns = new List<IScene>(1);
scns.Add(scene);
this.m_timerMap.Add(this.m_defaultState.Timer, scns);
}
}
}
bool tmpBusyCheck = ResolveBoolean("AutoBackupBusyCheck",
this.m_defaultState.BusyCheck, config, regionConfig);
if (state == null && tmpBusyCheck != this.m_defaultState.BusyCheck)
{
state = new AutoBackupModuleState();
}
if (state != null)
{
state.BusyCheck = tmpBusyCheck;
}
// Included Option To Skip Assets // Included Option To Skip Assets
bool tmpSkipAssets = ResolveBoolean("AutoBackupSkipAssets", state.SkipAssets = regionConfig.GetBoolean("AutoBackupSkipAssets", m_defaultState.SkipAssets);
this.m_defaultState.SkipAssets, config, regionConfig);
if (state == null && tmpSkipAssets != this.m_defaultState.SkipAssets)
{
state = new AutoBackupModuleState();
}
if (state != null)
{
state.SkipAssets = tmpSkipAssets;
}
// How long to keep backup files in days, 0 Disables this feature
int tmpKeepFilesForDays = ResolveInt("AutoBackupKeepFilesForDays",
this.m_defaultState.KeepFilesForDays, config, regionConfig);
if (state == null && tmpKeepFilesForDays != this.m_defaultState.KeepFilesForDays)
{
state = new AutoBackupModuleState();
}
if (state != null)
{
state.KeepFilesForDays = tmpKeepFilesForDays;
}
// Set file naming algorithm // Set file naming algorithm
string stmpNamingType = ResolveString("AutoBackupNaming", string stmpNamingType = regionConfig.GetString("AutoBackupNaming", m_defaultState.NamingType.ToString());
this.m_defaultState.NamingType.ToString(), config, regionConfig);
NamingType tmpNamingType; NamingType tmpNamingType;
if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase)) if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase))
{
tmpNamingType = NamingType.Time; tmpNamingType = NamingType.Time;
}
else if (stmpNamingType.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase)) else if (stmpNamingType.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase))
{
tmpNamingType = NamingType.Sequential; tmpNamingType = NamingType.Sequential;
}
else if (stmpNamingType.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase)) else if (stmpNamingType.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase))
{
tmpNamingType = NamingType.Overwrite; tmpNamingType = NamingType.Overwrite;
}
else else
{ {
m_log.Warn("Unknown naming type specified for region " + sRegionLabel + ": " + m_log.Warn("Unknown naming type specified for region " + sRegionName + ": " +
stmpNamingType); stmpNamingType);
tmpNamingType = NamingType.Time; tmpNamingType = NamingType.Time;
} }
m_defaultState.NamingType = tmpNamingType;
if (state == null && tmpNamingType != this.m_defaultState.NamingType) state.Script = regionConfig.GetString("AutoBackupScript", m_defaultState.Script);
{
state = new AutoBackupModuleState();
}
if (state != null)
{
state.NamingType = tmpNamingType;
}
string tmpScript = ResolveString("AutoBackupScript",
this.m_defaultState.Script, config, regionConfig);
if (state == null && tmpScript != this.m_defaultState.Script)
{
state = new AutoBackupModuleState();
}
if (state != null)
{
state.Script = tmpScript;
}
string tmpBackupDir = ResolveString("AutoBackupDir", ".", config, regionConfig);
if (state == null && tmpBackupDir != this.m_defaultState.BackupDir)
{
state = new AutoBackupModuleState();
}
if (state != null)
{
state.BackupDir = tmpBackupDir;
// Let's give the user some convenience and auto-mkdir
if (state.BackupDir != ".")
{
try
{
DirectoryInfo dirinfo = new DirectoryInfo(state.BackupDir);
if (!dirinfo.Exists)
{
dirinfo.Create();
}
}
catch (Exception e)
{
m_log.Warn(
"[AUTO BACKUP]: BAD NEWS. You won't be able to save backups to directory " +
state.BackupDir +
" because it doesn't exist or there's a permissions issue with it. Here's the exception.",
e);
}
}
}
if(state == null)
return m_defaultState;
return state; return state;
} }
/// <summary>
/// Helper function for ParseConfig.
/// </summary>
/// <param name="settingName"></param>
/// <param name="defaultValue"></param>
/// <param name="global"></param>
/// <param name="local"></param>
/// <returns></returns>
private bool ResolveBoolean(string settingName, bool defaultValue, IConfig global, IConfig local)
{
if(local != null)
{
return local.GetBoolean(settingName, global.GetBoolean(settingName, defaultValue));
}
else
{
return global.GetBoolean(settingName, defaultValue);
}
}
/// <summary>
/// Helper function for ParseConfig.
/// </summary>
/// <param name="settingName"></param>
/// <param name="defaultValue"></param>
/// <param name="global"></param>
/// <param name="local"></param>
/// <returns></returns>
private double ResolveDouble(string settingName, double defaultValue, IConfig global, IConfig local)
{
if (local != null)
{
return local.GetDouble(settingName, global.GetDouble(settingName, defaultValue));
}
else
{
return global.GetDouble(settingName, defaultValue);
}
}
/// <summary>
/// Helper function for ParseConfig.
/// </summary>
/// <param name="settingName"></param>
/// <param name="defaultValue"></param>
/// <param name="global"></param>
/// <param name="local"></param>
/// <returns></returns>
private int ResolveInt(string settingName, int defaultValue, IConfig global, IConfig local)
{
if (local != null)
{
return local.GetInt(settingName, global.GetInt(settingName, defaultValue));
}
else
{
return global.GetInt(settingName, defaultValue);
}
}
/// <summary>
/// Helper function for ParseConfig.
/// </summary>
/// <param name="settingName"></param>
/// <param name="defaultValue"></param>
/// <param name="global"></param>
/// <param name="local"></param>
/// <returns></returns>
private string ResolveString(string settingName, string defaultValue, IConfig global, IConfig local)
{
if (local != null)
{
return local.GetString(settingName, global.GetString(settingName, defaultValue));
}
else
{
return global.GetString(settingName, defaultValue);
}
}
/// <summary> /// <summary>
/// Called when any auto-backup timer expires. This starts the code path for actually performing a backup. /// Called when any auto-backup timer expires. This starts the code path for actually performing a backup.
@ -650,63 +442,27 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="e"></param> /// <param name="e"></param>
private void HandleElapsed(object sender, ElapsedEventArgs e) private void HandleElapsed(object sender, ElapsedEventArgs e)
{ {
// TODO: heuristic thresholds are per-region, so we should probably run heuristics once per region if (!m_enabled || m_busy)
// XXX: Running heuristics once per region could add undue performance penalty for something that's supposed to
// check whether the region is too busy! Especially on sims with LOTS of regions.
// Alternative: make heuristics thresholds global to the module rather than per-region. Less flexible,
// but would allow us to be semantically correct while being easier on perf.
// Alternative 2: Run heuristics once per unique set of heuristics threshold parameters! Ay yi yi...
// Alternative 3: Don't support per-region heuristics at all; just accept them as a global only parameter.
// Since this is pretty experimental, I haven't decided which alternative makes the most sense.
if (this.m_closed)
{
return; return;
}
bool heuristicsRun = false; m_busy = true;
bool heuristicsPassed = false; if(m_doneFirst && m_KeepFilesForDays > 0)
if (!this.m_timerMap.ContainsKey((Timer) sender)) RemoveOldFiles();
foreach (IScene scene in m_Scenes)
{ {
m_log.Debug("[AUTO BACKUP]: Code-up error: timerMap doesn't contain timer " + sender); if (!m_enabled)
return;
DoRegionBackup(scene);
} }
List<IScene> tmap = this.m_timerMap[(Timer) sender]; if (m_enabled)
if (tmap != null && tmap.Count > 0)
{ {
foreach (IScene scene in tmap) m_masterTimer.Start();
{ m_busy = false;
AutoBackupModuleState state = this.m_states[scene];
bool heuristics = state.BusyCheck;
// Fast path: heuristics are on; already ran em; and sim is fine; OR, no heuristics for the region.
if ((heuristics && heuristicsRun && heuristicsPassed) || !heuristics)
{
this.DoRegionBackup(scene);
// Heuristics are on; ran but we're too busy -- keep going. Maybe another region will have heuristics off!
}
else if (heuristicsRun)
{
m_log.Info("[AUTO BACKUP]: Heuristics: too busy to backup " +
scene.RegionInfo.RegionName + " right now.");
continue;
// Logical Deduction: heuristics are on but haven't been run
}
else
{
heuristicsPassed = this.RunHeuristics(scene);
heuristicsRun = true;
if (!heuristicsPassed)
{
m_log.Info("[AUTO BACKUP]: Heuristics: too busy to backup " +
scene.RegionInfo.RegionName + " right now.");
continue;
}
this.DoRegionBackup(scene);
} }
// Remove Old Backups m_doneFirst = true;
this.RemoveOldFiles(state);
}
}
} }
/// <summary> /// <summary>
@ -723,21 +479,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
return; return;
} }
AutoBackupModuleState state = this.m_states[scene]; m_busy = true;
AutoBackupModuleState state;
if(!m_states.TryGetValue(scene, out state))
return;
if(state == null || !state.Enabled)
return;
IRegionArchiverModule iram = scene.RequestModuleInterface<IRegionArchiverModule>(); IRegionArchiverModule iram = scene.RequestModuleInterface<IRegionArchiverModule>();
if(iram == null)
return;
string savePath = BuildOarPath(scene.RegionInfo.RegionName, string savePath = BuildOarPath(scene.RegionInfo.RegionName,
state.BackupDir, m_backupDir,
state.NamingType); state.NamingType);
if (savePath == null) if (savePath == null)
{ {
m_log.Warn("[AUTO BACKUP]: savePath is null in HandleElapsed"); m_log.Warn("[AUTO BACKUP]: savePath is null in HandleElapsed");
return; return;
} }
Guid guid = Guid.NewGuid();
m_pendingSaves.Add(guid, scene);
state.LiveRequests.Add(guid, savePath);
((Scene) scene).EventManager.OnOarFileSaved += new EventManager.OarFileSaved(EventManager_OnOarFileSaved);
Guid guid = Guid.NewGuid();
m_log.Info("[AUTO BACKUP]: Backing up region " + scene.RegionInfo.RegionName); m_log.Info("[AUTO BACKUP]: Backing up region " + scene.RegionInfo.RegionName);
// Must pass options, even if dictionary is empty! // Must pass options, even if dictionary is empty!
@ -747,16 +511,24 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
options["noassets"] = true; options["noassets"] = true;
iram.ArchiveRegion(savePath, guid, options); iram.ArchiveRegion(savePath, guid, options);
ExecuteScript(state.Script, savePath);
} }
// For the given state, remove backup files older than the states KeepFilesForDays property // For the given state, remove backup files older than the states KeepFilesForDays property
private void RemoveOldFiles(AutoBackupModuleState state) private void RemoveOldFiles()
{ {
// 0 Means Disabled, Keep Files Indefinitely string[] files;
if (state.KeepFilesForDays > 0) try
{ {
string[] files = Directory.GetFiles(state.BackupDir, "*.oar"); files = Directory.GetFiles(m_backupDir, "*.oar");
DateTime CuttOffDate = DateTime.Now.AddDays(0 - state.KeepFilesForDays); }
catch (Exception Ex)
{
m_log.Error("[AUTO BACKUP]: Error reading backup folder " + m_backupDir + ": " + Ex.Message);
return;
}
DateTime CuttOffDate = DateTime.Now.AddDays(-m_KeepFilesForDays);
foreach (string file in files) foreach (string file in files)
{ {
@ -772,24 +544,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
} }
} }
} }
}
/// <summary>
/// Called by the Event Manager when the OnOarFileSaved event is fired.
/// </summary>
/// <param name="guid"></param>
/// <param name="message"></param>
void EventManager_OnOarFileSaved(Guid guid, string message)
{
// Ignore if the OAR save is being done by some other part of the system
if (m_pendingSaves.ContainsKey(guid))
{
AutoBackupModuleState abms = m_states[(m_pendingSaves[guid])];
ExecuteScript(abms.Script, abms.LiveRequests[guid]);
m_pendingSaves.Remove(guid);
abms.LiveRequests.Remove(guid);
}
}
/// <summary>This format may turn out to be too unwieldy to keep... /// <summary>This format may turn out to be too unwieldy to keep...
/// Besides, that's what ctimes are for. But then how do I name each file uniquely without using a GUID? /// Besides, that's what ctimes are for. But then how do I name each file uniquely without using a GUID?
@ -817,63 +571,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
return output; return output;
} }
/// <summary>Return value of true ==> not too busy; false ==> too busy to backup an OAR right now, or error.</summary>
private bool RunHeuristics(IScene region)
{
try
{
return this.RunTimeDilationHeuristic(region) && this.RunAgentLimitHeuristic(region);
}
catch (Exception e)
{
m_log.Warn("[AUTO BACKUP]: Exception in RunHeuristics", e);
return false;
}
}
/// <summary>
/// If the time dilation right at this instant is less than the threshold specified in AutoBackupDilationThreshold (default 0.5),
/// then we return false and trip the busy heuristic's "too busy" path (i.e. don't save an OAR).
/// AutoBackupDilationThreshold is a _LOWER BOUND_. Lower Time Dilation is bad, so if you go lower than our threshold, it's "too busy".
/// </summary>
/// <param name="region"></param>
/// <returns>Returns true if we're not too busy; false means we've got worse time dilation than the threshold.</returns>
private bool RunTimeDilationHeuristic(IScene region)
{
string regionName = region.RegionInfo.RegionName;
return region.TimeDilation >=
this.m_configSource.Configs["AutoBackupModule"].GetFloat(
regionName + ".AutoBackupDilationThreshold", 0.5f);
}
/// <summary>
/// If the root agent count right at this instant is less than the threshold specified in AutoBackupAgentThreshold (default 10),
/// then we return false and trip the busy heuristic's "too busy" path (i.e., don't save an OAR).
/// AutoBackupAgentThreshold is an _UPPER BOUND_. Higher Agent Count is bad, so if you go higher than our threshold, it's "too busy".
/// </summary>
/// <param name="region"></param>
/// <returns>Returns true if we're not too busy; false means we've got more agents on the sim than the threshold.</returns>
private bool RunAgentLimitHeuristic(IScene region)
{
string regionName = region.RegionInfo.RegionName;
try
{
Scene scene = (Scene) region;
// TODO: Why isn't GetRootAgentCount() a method in the IScene interface? Seems generally useful...
return scene.GetRootAgentCount() <=
this.m_configSource.Configs["AutoBackupModule"].GetInt(
regionName + ".AutoBackupAgentThreshold", 10);
}
catch (InvalidCastException ice)
{
m_log.Debug(
"[AUTO BACKUP]: I NEED MAINTENANCE: IScene is not a Scene; can't get root agent count!",
ice);
return true;
// Non-obstructionist safest answer...
}
}
/// <summary> /// <summary>
/// Run the script or executable specified by the "AutoBackupScript" config setting. /// Run the script or executable specified by the "AutoBackupScript" config setting.
/// Of course this is a security risk if you let anyone modify OpenSim.ini and they want to run some nasty bash script. /// Of course this is a security risk if you let anyone modify OpenSim.ini and they want to run some nasty bash script.
@ -919,18 +616,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
" is yacking on stderr: " + e.Data); " is yacking on stderr: " + e.Data);
} }
/// <summary>
/// Quickly stop all timers from firing.
/// </summary>
private void StopAllTimers()
{
foreach (Timer t in this.m_timerMap.Keys)
{
t.Close();
}
this.m_closed = true;
}
/// <summary> /// <summary>
/// Determine the next unique filename by number, for "Sequential" AutoBackupNamingType. /// Determine the next unique filename by number, for "Sequential" AutoBackupNamingType.
/// </summary> /// </summary>
@ -1033,5 +718,3 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
} }
} }
} }

View File

@ -38,26 +38,20 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// ///
public class AutoBackupModuleState public class AutoBackupModuleState
{ {
private Dictionary<Guid, string> m_liveRequests = null;
public AutoBackupModuleState() public AutoBackupModuleState()
{ {
this.Enabled = false; Enabled = false;
this.BackupDir = "."; SkipAssets = false;
this.BusyCheck = true; NamingType = NamingType.Time;
this.SkipAssets = false; Script = null;
this.Timer = null;
this.NamingType = NamingType.Time;
this.Script = null;
this.KeepFilesForDays = 0;
} }
public Dictionary<Guid, string> LiveRequests public AutoBackupModuleState(AutoBackupModuleState copyFrom)
{ {
get { Enabled = copyFrom.Enabled;
return this.m_liveRequests ?? SkipAssets = copyFrom.SkipAssets;
(this.m_liveRequests = new Dictionary<Guid, string>(1)); NamingType = copyFrom.NamingType;
} Script = copyFrom.Script;
} }
public bool Enabled public bool Enabled
@ -66,33 +60,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
set; set;
} }
public System.Timers.Timer Timer
{
get;
set;
}
public double IntervalMinutes
{
get
{
if (this.Timer == null)
{
return -1.0;
}
else
{
return this.Timer.Interval / 60000.0;
}
}
}
public bool BusyCheck
{
get;
set;
}
public bool SkipAssets public bool SkipAssets
{ {
get; get;
@ -105,36 +72,19 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
set; set;
} }
public string BackupDir
{
get;
set;
}
public NamingType NamingType public NamingType NamingType
{ {
get; get;
set; set;
} }
public int KeepFilesForDays
{
get;
set;
}
public new string ToString() public new string ToString()
{ {
string retval = ""; string retval = "";
retval += "[AUTO BACKUP]: AutoBackup: " + (Enabled ? "ENABLED" : "DISABLED") + "\n"; retval += "[AUTO BACKUP]: AutoBackup: " + (Enabled ? "ENABLED" : "DISABLED") + "\n";
retval += "[AUTO BACKUP]: Interval: " + IntervalMinutes + " minutes" + "\n";
retval += "[AUTO BACKUP]: Do Busy Check: " + (BusyCheck ? "Yes" : "No") + "\n";
retval += "[AUTO BACKUP]: Naming Type: " + NamingType.ToString() + "\n"; retval += "[AUTO BACKUP]: Naming Type: " + NamingType.ToString() + "\n";
retval += "[AUTO BACKUP]: Backup Dir: " + BackupDir + "\n";
retval += "[AUTO BACKUP]: Script: " + Script + "\n"; retval += "[AUTO BACKUP]: Script: " + Script + "\n";
return retval; return retval;
} }
} }
} }

View File

@ -27,8 +27,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Reflection; using System.Reflection;
using System.Timers; using System.Timers;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using OpenMetaverse; using OpenMetaverse;
using log4net; using log4net;
using Mono.Addins; using Mono.Addins;
@ -38,9 +43,7 @@ using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using System.Xml; using Timer= System.Timers.Timer;
using System.Xml.Serialization;
using System.IO;
namespace OpenSim.Region.OptionalModules.World.TreePopulator namespace OpenSim.Region.OptionalModules.World.TreePopulator
{ {
@ -48,7 +51,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
/// Version 2.02 - Still hacky /// Version 2.02 - Still hacky
/// </summary> /// </summary>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TreePopulatorModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TreePopulatorModule")]
public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule, IVegetationModule public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly Commander m_commander = new Commander("tree"); private readonly Commander m_commander = new Commander("tree");
@ -82,20 +85,20 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
{ {
Copse cp = (Copse)DeserializeObject(fileName); Copse cp = (Copse)DeserializeObject(fileName);
this.m_name = cp.m_name; m_name = cp.m_name;
this.m_frozen = cp.m_frozen; m_frozen = cp.m_frozen;
this.m_tree_quantity = cp.m_tree_quantity; m_tree_quantity = cp.m_tree_quantity;
this.m_treeline_high = cp.m_treeline_high; m_treeline_high = cp.m_treeline_high;
this.m_treeline_low = cp.m_treeline_low; m_treeline_low = cp.m_treeline_low;
this.m_range = cp.m_range; m_range = cp.m_range;
this.m_tree_type = cp.m_tree_type; m_tree_type = cp.m_tree_type;
this.m_seed_point = cp.m_seed_point; m_seed_point = cp.m_seed_point;
this.m_initial_scale = cp.m_initial_scale; m_initial_scale = cp.m_initial_scale;
this.m_maximum_scale = cp.m_maximum_scale; m_maximum_scale = cp.m_maximum_scale;
this.m_initial_scale = cp.m_initial_scale; m_initial_scale = cp.m_initial_scale;
this.m_rate = cp.m_rate; m_rate = cp.m_rate;
this.m_planted = planted; m_planted = planted;
this.m_trees = new List<UUID>(); m_trees = new List<UUID>();
} }
public Copse(string copsedef) public Copse(string copsedef)
@ -103,61 +106,63 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
char[] delimiterChars = {':', ';'}; char[] delimiterChars = {':', ';'};
string[] field = copsedef.Split(delimiterChars); string[] field = copsedef.Split(delimiterChars);
this.m_name = field[1].Trim(); m_name = field[1].Trim();
this.m_frozen = (copsedef[0] == 'F'); m_frozen = (copsedef[0] == 'F');
this.m_tree_quantity = int.Parse(field[2]); m_tree_quantity = int.Parse(field[2]);
this.m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo); m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo);
this.m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo); m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo);
this.m_range = double.Parse(field[5], Culture.NumberFormatInfo); m_range = double.Parse(field[5], Culture.NumberFormatInfo);
this.m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]); m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]);
this.m_seed_point = Vector3.Parse(field[7]); m_seed_point = Vector3.Parse(field[7]);
this.m_initial_scale = Vector3.Parse(field[8]); m_initial_scale = Vector3.Parse(field[8]);
this.m_maximum_scale = Vector3.Parse(field[9]); m_maximum_scale = Vector3.Parse(field[9]);
this.m_rate = Vector3.Parse(field[10]); m_rate = Vector3.Parse(field[10]);
this.m_planted = true; m_planted = true;
this.m_trees = new List<UUID>(); m_trees = new List<UUID>();
} }
public Copse(string name, int quantity, float high, float low, double range, Vector3 point, Tree type, Vector3 scale, Vector3 max_scale, Vector3 rate, List<UUID> trees) public Copse(string name, int quantity, float high, float low, double range, Vector3 point, Tree type, Vector3 scale, Vector3 max_scale, Vector3 rate, List<UUID> trees)
{ {
this.m_name = name; m_name = name;
this.m_frozen = false; m_frozen = false;
this.m_tree_quantity = quantity; m_tree_quantity = quantity;
this.m_treeline_high = high; m_treeline_high = high;
this.m_treeline_low = low; m_treeline_low = low;
this.m_range = range; m_range = range;
this.m_tree_type = type; m_tree_type = type;
this.m_seed_point = point; m_seed_point = point;
this.m_initial_scale = scale; m_initial_scale = scale;
this.m_maximum_scale = max_scale; m_maximum_scale = max_scale;
this.m_rate = rate; m_rate = rate;
this.m_planted = false; m_planted = false;
this.m_trees = trees; m_trees = trees;
} }
public override string ToString() public override string ToString()
{ {
string frozen = (this.m_frozen ? "F" : "A"); string frozen = (m_frozen ? "F" : "A");
return string.Format("{0}TPM: {1}; {2}; {3:0.0}; {4:0.0}; {5:0.0}; {6}; {7:0.0}; {8:0.0}; {9:0.0}; {10:0.00};", return string.Format("{0}TPM: {1}; {2}; {3:0.0}; {4:0.0}; {5:0.0}; {6}; {7:0.0}; {8:0.0}; {9:0.0}; {10:0.00};",
frozen, frozen,
this.m_name, m_name,
this.m_tree_quantity, m_tree_quantity,
this.m_treeline_high, m_treeline_high,
this.m_treeline_low, m_treeline_low,
this.m_range, m_range,
this.m_tree_type, m_tree_type,
this.m_seed_point.ToString(), m_seed_point.ToString(),
this.m_initial_scale.ToString(), m_initial_scale.ToString(),
this.m_maximum_scale.ToString(), m_maximum_scale.ToString(),
this.m_rate.ToString()); m_rate.ToString());
} }
} }
private List<Copse> m_copse; private List<Copse> m_copses = new List<Copse>();
private object mylock;
private double m_update_ms = 1000.0; // msec between updates private double m_update_ms = 1000.0; // msec between updates
private bool m_active_trees = false; private bool m_active_trees = false;
private bool m_enabled = true; // original default
private bool m_allowGrow = true; // original default
Timer CalculateTrees; Timer CalculateTrees;
@ -174,51 +179,51 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
public void Initialise(IConfigSource config) public void Initialise(IConfigSource config)
{ {
IConfig moduleConfig = config.Configs["Trees"];
// ini file settings if (moduleConfig != null)
try
{ {
m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees); m_enabled = moduleConfig.GetBoolean("enabled", m_enabled);
} m_active_trees = moduleConfig.GetBoolean("active_trees", m_active_trees);
catch (Exception) m_allowGrow = moduleConfig.GetBoolean("allowGrow", m_allowGrow);
{ m_update_ms = moduleConfig.GetDouble("update_rate", m_update_ms);
m_log.Debug("[TREES]: ini failure for active_trees - using default");
} }
try if(!m_enabled)
{ return;
m_update_ms = config.Configs["Trees"].GetDouble("update_rate", m_update_ms);
} m_copses = new List<Copse>();
catch (Exception) mylock = new object();
{
m_log.Debug("[TREES]: ini failure for update_rate - using default");
}
InstallCommands(); InstallCommands();
m_log.Debug("[TREES]: Initialised tree module"); m_log.Debug("[TREES]: Initialised tree populator module");
} }
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
{ {
if(!m_enabled)
return;
m_scene = scene; m_scene = scene;
m_scene.RegisterModuleCommander(m_commander); m_scene.RegisterModuleCommander(m_commander);
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
m_scene.EventManager.OnPrimsLoaded += EventManager_OnPrimsLoaded;
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
{ {
if(!m_enabled)
return;
if(m_active_trees && CalculateTrees != null)
{
CalculateTrees.Dispose();
CalculateTrees = null;
}
m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
m_scene.EventManager.OnPrimsLoaded -= EventManager_OnPrimsLoaded;
} }
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
{ {
ReloadCopse();
if (m_copse.Count > 0)
m_log.Info("[TREES]: Copse load complete");
if (m_active_trees)
activeizeTreeze(true);
} }
public void Close() public void Close()
@ -240,6 +245,16 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
//-------------------------------------------------------------- //--------------------------------------------------------------
private void EventManager_OnPrimsLoaded(Scene s)
{
ReloadCopse();
if (m_copses.Count > 0)
m_log.Info("[TREES]: Copses loaded" );
if (m_active_trees)
activeizeTreeze(true);
}
#region ICommandableModule Members #region ICommandableModule Members
private void HandleTreeActive(Object[] args) private void HandleTreeActive(Object[] args)
@ -267,27 +282,59 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
string copsename = ((string)args[0]).Trim(); string copsename = ((string)args[0]).Trim();
Boolean freezeState = (Boolean) args[1]; Boolean freezeState = (Boolean) args[1];
foreach (Copse cp in m_copse) lock(mylock)
{ {
if (cp.m_name == copsename && (!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)) foreach (Copse cp in m_copses)
{
if (cp.m_name != copsename)
continue;
if(!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)
{ {
cp.m_frozen = freezeState; cp.m_frozen = freezeState;
List<UUID> losttrees = new List<UUID>();
foreach (UUID tree in cp.m_trees) foreach (UUID tree in cp.m_trees)
{ {
SceneObjectPart sop = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
sop.Name = (freezeState ? sop.Name.Replace("ATPM", "FTPM") : sop.Name.Replace("FTPM", "ATPM")); if(sog != null && !sog.IsDeleted)
sop.ParentGroup.HasGroupChanged = true; {
SceneObjectPart sop = sog.RootPart;
string name = sop.Name;
if(freezeState)
{
if(name.StartsWith("FTPM"))
continue;
if(!name.StartsWith("ATPM"))
continue;
sop.Name = sop.Name.Replace("ATPM", "FTPM");
} }
else
{
if(name.StartsWith("ATPM"))
continue;
if(!name.StartsWith("FTPM"))
continue;
sop.Name = sop.Name.Replace("FTPM", "ATPM");
}
sop.ParentGroup.HasGroupChanged = true;
sog.ScheduleGroupForFullUpdate();
}
else
losttrees.Add(tree);
}
foreach (UUID tree in losttrees)
cp.m_trees.Remove(tree);
m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState); m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState);
return; return;
} }
else if (cp.m_name == copsename && (cp.m_frozen && freezeState || !cp.m_frozen && !freezeState)) else
{ {
m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename); m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename);
return; return;
} }
} }
}
m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename); m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
} }
@ -297,8 +344,11 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_log.InfoFormat("[TREES]: Loading copse definition...."); m_log.InfoFormat("[TREES]: Loading copse definition....");
lock(mylock)
{
copse = new Copse(((string)args[0]), false); copse = new Copse(((string)args[0]), false);
foreach (Copse cp in m_copse) {
foreach (Copse cp in m_copses)
{ {
if (cp.m_name == copse.m_name) if (cp.m_name == copse.m_name)
{ {
@ -306,8 +356,9 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
return; return;
} }
} }
}
m_copse.Add(copse); m_copses.Add(copse);
}
m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString()); m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString());
} }
@ -318,20 +369,24 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename); m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename);
UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
foreach (Copse copse in m_copse) lock(mylock)
{
foreach (Copse copse in m_copses)
{ {
if (copse.m_name == copsename) if (copse.m_name == copsename)
{ {
if (!copse.m_planted) if (!copse.m_planted)
{ {
// The first tree for a copse is created here // The first tree for a copse is created here
CreateTree(uuid, copse, copse.m_seed_point); CreateTree(uuid, copse, copse.m_seed_point, true);
copse.m_planted = true; copse.m_planted = true;
return; return;
} }
else else
{ {
m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename); m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename);
return;
}
} }
} }
} }
@ -376,7 +431,9 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
string copsename = ((string)args[0]).Trim(); string copsename = ((string)args[0]).Trim();
Copse copseIdentity = null; Copse copseIdentity = null;
foreach (Copse cp in m_copse) lock(mylock)
{
foreach (Copse cp in m_copses)
{ {
if (cp.m_name == copsename) if (cp.m_name == copsename)
{ {
@ -399,8 +456,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
} }
} }
copseIdentity.m_trees = new List<UUID>(); copseIdentity.m_trees = null;
m_copse.Remove(copseIdentity); m_copses.Remove(copseIdentity);
m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename); m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename);
} }
else else
@ -408,11 +465,13 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename); m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
} }
} }
}
private void HandleTreeStatistics(Object[] args) private void HandleTreeStatistics(Object[] args)
{ {
m_log.InfoFormat("[TREES]: region {0}:", m_scene.Name);
m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms); m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms);
foreach (Copse cp in m_copse) foreach (Copse cp in m_copses)
{ {
m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen); m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen);
} }
@ -442,7 +501,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double"); treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double");
Command treeReloadCommand = Command treeReloadCommand =
new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copse definitions from the in-scene trees"); new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copses from the in-scene trees");
Command treeRemoveCommand = Command treeRemoveCommand =
new Command("remove", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeRemove, "Remove a copse definition and all its in-scene trees"); new Command("remove", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeRemove, "Remove a copse definition and all its in-scene trees");
@ -499,34 +558,17 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
treeShape.Scale = scale; treeShape.Scale = scale;
treeShape.State = (byte)treeType; treeShape.State = (byte)treeType;
return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); SceneObjectGroup sog = new SceneObjectGroup(uuid, position, rotation, treeShape);
} SceneObjectPart rootPart = sog.RootPart;
#endregion
#region IEntityCreator Members
protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.NewTree, PCode.Tree };
public PCode[] CreationCapabilities { get { return creationCapabilities; } }
public SceneObjectGroup CreateEntity(
UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
{
if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0)
{
m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name);
return null;
}
SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID);
rootPart.AddFlag(PrimFlags.Phantom); rootPart.AddFlag(PrimFlags.Phantom);
sceneObject.SetGroup(groupID, null); sog.SetGroup(groupID, null);
m_scene.AddNewSceneObject(sceneObject, true); m_scene.AddNewSceneObject(sog, true, false);
sceneObject.InvalidateEffectivePerms(); sog.IsSelected = false;
return sceneObject; rootPart.IsSelected = false;
sog.InvalidateEffectivePerms();
return sog;
} }
#endregion #endregion
@ -569,14 +611,13 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
private void ReloadCopse() private void ReloadCopse()
{ {
m_copse = new List<Copse>(); m_copses = new List<Copse>();
EntityBase[] objs = m_scene.GetEntities(); List<SceneObjectGroup> grps = m_scene.GetSceneObjectGroups();
foreach (EntityBase obj in objs) foreach (SceneObjectGroup grp in grps)
{ {
if (obj is SceneObjectGroup) if(grp.RootPart.Shape.PCode != (byte)PCode.NewTree && grp.RootPart.Shape.PCode != (byte)PCode.Tree)
{ continue;
SceneObjectGroup grp = (SceneObjectGroup)obj;
if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:")) if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:"))
{ {
@ -584,11 +625,13 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
try try
{ {
Boolean copsefound = false; Boolean copsefound = false;
Copse copse = new Copse(grp.Name); Copse grpcopse = new Copse(grp.Name);
foreach (Copse cp in m_copse) lock(mylock)
{ {
if (cp.m_name == copse.m_name) foreach (Copse cp in m_copses)
{
if (cp.m_name == grpcopse.m_name)
{ {
copsefound = true; copsefound = true;
cp.m_trees.Add(grp.UUID); cp.m_trees.Add(grp.UUID);
@ -598,9 +641,10 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
if (!copsefound) if (!copsefound)
{ {
m_log.InfoFormat("[TREES]: Found copse {0}", grp.Name); m_log.InfoFormat("[TREES]: adding copse {0}", grpcopse.m_name);
m_copse.Add(copse); grpcopse.m_trees.Add(grp.UUID);
copse.m_trees.Add(grp.UUID); m_copses.Add(grpcopse);
}
} }
} }
catch catch
@ -610,15 +654,16 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
} }
} }
} }
}
#endregion #endregion
private void activeizeTreeze(bool activeYN) private void activeizeTreeze(bool activeYN)
{ {
if (activeYN) if (activeYN)
{ {
if(CalculateTrees == null)
CalculateTrees = new Timer(m_update_ms); CalculateTrees = new Timer(m_update_ms);
CalculateTrees.Elapsed += CalculateTrees_Elapsed; CalculateTrees.Elapsed += CalculateTrees_Elapsed;
CalculateTrees.AutoReset = false;
CalculateTrees.Start(); CalculateTrees.Start();
} }
else else
@ -629,155 +674,252 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
private void growTrees() private void growTrees()
{ {
foreach (Copse copse in m_copse) if(!m_allowGrow)
{ return;
if (!copse.m_frozen)
foreach (Copse copse in m_copses)
{ {
if (copse.m_frozen)
continue;
if(copse.m_trees.Count == 0)
continue;
float maxscale = copse.m_maximum_scale.Z;
float ratescale = 1.0f;
List<UUID> losttrees = new List<UUID>();
foreach (UUID tree in copse.m_trees) foreach (UUID tree in copse.m_trees)
{ {
if (m_scene.Entities.ContainsKey(tree)) SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
{
SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
if (s_tree.Scale.X < copse.m_maximum_scale.X && s_tree.Scale.Y < copse.m_maximum_scale.Y && s_tree.Scale.Z < copse.m_maximum_scale.Z) if (sog != null && !sog.IsDeleted)
{ {
s_tree.Scale += copse.m_rate; SceneObjectPart s_tree = sog.RootPart;
s_tree.ParentGroup.HasGroupChanged = true; if (s_tree.Scale.Z < maxscale)
{
ratescale = (float)Util.RandomClass.NextDouble();
if(ratescale < 0.2f)
ratescale = 0.2f;
s_tree.Scale += copse.m_rate * ratescale;
sog.HasGroupChanged = true;
s_tree.ScheduleFullUpdate(); s_tree.ScheduleFullUpdate();
} }
} }
else else
{ losttrees.Add(tree);
m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
}
}
} }
foreach (UUID tree in losttrees)
copse.m_trees.Remove(tree);
} }
} }
private void seedTrees() private void seedTrees()
{ {
foreach (Copse copse in m_copse) foreach (Copse copse in m_copses)
{ {
if (!copse.m_frozen) if (copse.m_frozen)
{ continue;
foreach (UUID tree in copse.m_trees)
{
if (m_scene.Entities.ContainsKey(tree))
{
SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
if (copse.m_trees.Count < copse.m_tree_quantity) if(copse.m_trees.Count == 0)
return;
bool low = copse.m_trees.Count < (int)(copse.m_tree_quantity * 0.8f);
if (!low && Util.RandomClass.NextDouble() < 0.75)
return;
int maxbirths = (int)(copse.m_tree_quantity) - copse.m_trees.Count;
if(maxbirths <= 1)
return;
if(maxbirths > 20)
maxbirths = 20;
float minscale = 0;
if(!low && m_allowGrow)
minscale = copse.m_maximum_scale.Z * 0.75f;;
int i = 0;
UUID[] current = copse.m_trees.ToArray();
while(--maxbirths > 0)
{ {
if(current.Length > 1)
i = Util.RandomClass.Next(current.Length -1);
UUID tree = current[i];
SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
if (sog != null && !sog.IsDeleted)
{
SceneObjectPart s_tree = sog.RootPart;
// Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height
if (s_tree.Scale.Z > copse.m_initial_scale.Z + (copse.m_maximum_scale.Z - copse.m_initial_scale.Z) / 4.0) if (s_tree.Scale.Z > minscale)
{ SpawnChild(copse, s_tree, true);
if (Util.RandomClass.NextDouble() > 0.75)
{
SpawnChild(copse, s_tree);
}
}
}
}
else
{
m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
}
} }
else if(copse.m_trees.Contains(tree))
copse.m_trees.Remove(tree);
} }
} }
} }
private void killTrees() private void killTrees()
{ {
foreach (Copse copse in m_copse) foreach (Copse copse in m_copses)
{ {
if (!copse.m_frozen && copse.m_trees.Count >= copse.m_tree_quantity) if (copse.m_frozen)
{ continue;
foreach (UUID tree in copse.m_trees)
{
double killLikelyhood = 0.0;
if (m_scene.Entities.ContainsKey(tree)) if (Util.RandomClass.NextDouble() < 0.25)
return;
int maxbdeaths = copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) ;
if(maxbdeaths < 1)
return;
float odds;
float scale = 1.0f / copse.m_maximum_scale.Z;
int ntries = maxbdeaths * 4;
while(ntries-- > 0 )
{ {
SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; int next = 0;
double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) + if (copse.m_trees.Count > 1)
Math.Pow(selectedTree.Scale.Y, 2) + next = Util.RandomClass.Next(copse.m_trees.Count - 1);
Math.Pow(selectedTree.Scale.Z, 2)); UUID tree = copse.m_trees[next];
SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
foreach (UUID picktree in copse.m_trees) if (sog != null && !sog.IsDeleted)
{ {
if (picktree != tree) if(m_allowGrow)
{ {
SceneObjectPart pickedTree = ((SceneObjectGroup)m_scene.Entities[picktree]).RootPart; odds = sog.RootPart.Scale.Z * scale;
odds = odds * odds * odds;
double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) + odds *= (float)Util.RandomClass.NextDouble();
Math.Pow(pickedTree.Scale.Y, 2) +
Math.Pow(pickedTree.Scale.Z, 2));
double pickedTreeDistance = Vector3.Distance(pickedTree.AbsolutePosition, selectedTree.AbsolutePosition);
killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1;
} }
else
{
odds = (float)Util.RandomClass.NextDouble();
odds = odds * odds * odds;
} }
if (Util.RandomClass.NextDouble() < killLikelyhood) if(odds > 0.9f)
{ {
// Delete tree and alert clients (not silent) m_scene.DeleteSceneObject(sog, false);
m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); if(maxbdeaths <= 0)
copse.m_trees.Remove(selectedTree.ParentGroup.UUID);
break; break;
} }
} }
else else
{ {
m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); copse.m_trees.Remove(tree);
} if(copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) <= 0 )
break;
} }
} }
} }
} }
private void SpawnChild(Copse copse, SceneObjectPart s_tree) private void SpawnChild(Copse copse, SceneObjectPart s_tree, bool low)
{ {
Vector3 position = new Vector3(); Vector3 position = new Vector3();
double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); float randX = copse.m_maximum_scale.X * 1.25f;
double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); float randY = copse.m_maximum_scale.Y * 1.25f;
float r = (float)Util.RandomClass.NextDouble();
randX *= 2.0f * r - 1.0f;
position.X = s_tree.AbsolutePosition.X + (float)randX; position.X = s_tree.AbsolutePosition.X + (float)randX;
r = (float)Util.RandomClass.NextDouble();
randY *= 2.0f * r - 1.0f;
position.Y = s_tree.AbsolutePosition.Y + (float)randY; position.Y = s_tree.AbsolutePosition.Y + (float)randY;
if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 && if (position.X > (m_scene.RegionInfo.RegionSizeX - 1) || position.X <= 0 ||
position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 && position.Y > (m_scene.RegionInfo.RegionSizeY - 1) || position.Y <= 0)
Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range) return;
{
randX = position.X - copse.m_seed_point.X;
randX *= randX;
randY = position.Y - copse.m_seed_point.Y;
randY *= randY;
randX += randY;
if(randX > copse.m_range * copse.m_range)
return;
UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
CreateTree(uuid, copse, position, low);
CreateTree(uuid, copse, position);
}
} }
private void CreateTree(UUID uuid, Copse copse, Vector3 position) private void CreateTree(UUID uuid, Copse copse, Vector3 position, bool randomScale)
{ {
position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y]; position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y];
if (position.Z >= copse.m_treeline_low && position.Z <= copse.m_treeline_high) if (position.Z < copse.m_treeline_low || position.Z > copse.m_treeline_high)
{ return;
SceneObjectGroup tree = AddTree(uuid, UUID.Zero, copse.m_initial_scale, Quaternion.Identity, position, copse.m_tree_type, false);
Vector3 scale = copse.m_initial_scale;
if(randomScale)
{
try
{
float t;
float r = (float)Util.RandomClass.NextDouble();
r *= (float)Util.RandomClass.NextDouble();
r *= (float)Util.RandomClass.NextDouble();
t = copse.m_maximum_scale.X / copse.m_initial_scale.X;
if(t < 1.0)
t = 1 / t;
t = t * r + 1.0f;
scale.X *= t;
t = copse.m_maximum_scale.Y / copse.m_initial_scale.Y;
if(t < 1.0)
t = 1 / t;
t = t * r + 1.0f;
scale.Y *= t;
t = copse.m_maximum_scale.Z / copse.m_initial_scale.Z;
if(t < 1.0)
t = 1 / t;
t = t * r + 1.0f;
scale.Z *= t;
}
catch
{
scale = copse.m_initial_scale;
}
}
SceneObjectGroup tree = AddTree(uuid, UUID.Zero, scale, Quaternion.Identity, position, copse.m_tree_type, false);
tree.Name = copse.ToString(); tree.Name = copse.ToString();
copse.m_trees.Add(tree.UUID); copse.m_trees.Add(tree.UUID);
tree.SendGroupFullUpdate(); tree.RootPart.ScheduleFullUpdate();
}
} }
private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e) private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e)
{
if(!m_scene.IsRunning)
return;
if(Monitor.TryEnter(mylock))
{
try
{
if(m_scene.LoginsEnabled )
{ {
growTrees(); growTrees();
seedTrees(); seedTrees();
killTrees(); killTrees();
} }
} }
catch { }
if(CalculateTrees != null)
CalculateTrees.Start();
Monitor.Exit(mylock);
}
}
}
} }

View File

@ -103,7 +103,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
public float walkDivisor = 1.3f; public float walkDivisor = 1.3f;
public float runDivisor = 0.8f; public float runDivisor = 0.8f;
private bool flying = false; private bool m_flying = false;
private bool m_iscolliding = false; private bool m_iscolliding = false;
private bool m_iscollidingGround = false; private bool m_iscollidingGround = false;
private bool m_iscollidingObj = false; private bool m_iscollidingObj = false;
@ -298,10 +298,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
public override bool Flying public override bool Flying
{ {
get { return flying; } get { return m_flying; }
set set
{ {
flying = value; m_flying = value;
// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying); // m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
} }
} }
@ -943,12 +943,13 @@ namespace OpenSim.Region.PhysicsModule.ubOde
} }
return true; return true;
} }
/*
d.AABB aabb; if (gtype == d.GeomClassID.SphereClass && d.GeomGetBody(other) != IntPtr.Zero)
d.GeomGetAABB(other,out aabb); {
float othertop = aabb.MaxZ - _position.Z; if(d.GeomSphereGetRadius(other) < 0.5)
*/ return true;
// if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f) }
if (offset.Z > 0 || contact.normal.Z > 0.35f) if (offset.Z > 0 || contact.normal.Z > 0.35f)
{ {
if (offset.Z <= 0) if (offset.Z <= 0)
@ -965,6 +966,18 @@ namespace OpenSim.Region.PhysicsModule.ubOde
return true; return true;
} }
if(m_flying)
return true;
feetcollision = true;
if (h < boneOff)
{
m_collideNormal.X = contact.normal.X;
m_collideNormal.Y = contact.normal.Y;
m_collideNormal.Z = contact.normal.Z;
IsColliding = true;
}
altContact = contact; altContact = contact;
useAltcontact = true; useAltcontact = true;
@ -972,8 +985,21 @@ namespace OpenSim.Region.PhysicsModule.ubOde
offset.Normalize(); offset.Normalize();
if (contact.depth > 0.1f) float tdp = contact.depth;
contact.depth = 0.1f; float t = offset.X;
t = Math.Abs(t);
if(t > 1e-6)
{
tdp /= t;
tdp *= contact.normal.X;
}
else
tdp *= 10;
if (tdp > 0.25f)
tdp = 0.25f;
altContact.depth = tdp;
if (reverse) if (reverse)
{ {
@ -987,15 +1013,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
altContact.normal.Y = -offset.Y; altContact.normal.Y = -offset.Y;
altContact.normal.Z = -offset.Z; altContact.normal.Z = -offset.Z;
} }
feetcollision = true;
if (h < boneOff)
{
m_collideNormal.X = contact.normal.X;
m_collideNormal.Y = contact.normal.Y;
m_collideNormal.Z = contact.normal.Z;
IsColliding = true;
}
return true; return true;
} }
return false; return false;
@ -1098,7 +1115,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
float ftmp; float ftmp;
if (flying) if (m_flying)
{ {
ftmp = timeStep; ftmp = timeStep;
posch.X += vel.X * ftmp; posch.X += vel.X * ftmp;
@ -1122,7 +1139,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
vec.Z = depth * PID_P * 50; vec.Z = depth * PID_P * 50;
if (!flying) if (!m_flying)
{ {
vec.Z += -vel.Z * PID_D; vec.Z += -vel.Z * PID_D;
if(n.Z < 0.4f) if(n.Z < 0.4f)
@ -1259,7 +1276,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
// movement relative to surface if moving on it // movement relative to surface if moving on it
// dont disturbe vertical movement, ie jumps // dont disturbe vertical movement, ie jumps
if (m_iscolliding && !flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f) if (m_iscolliding && !m_flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f)
{ {
float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y; float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y;
ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X); ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X);
@ -1276,7 +1293,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
{ {
// if velocity is zero, use position control; otherwise, velocity control // if velocity is zero, use position control; otherwise, velocity control
if (tviszero && m_iscolliding && !flying) if (tviszero && m_iscolliding && !m_flying)
{ {
// keep track of where we stopped. No more slippin' & slidin' // keep track of where we stopped. No more slippin' & slidin'
if (!_zeroFlag) if (!_zeroFlag)
@ -1313,7 +1330,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_iscolliding) if (m_iscolliding)
{ {
if (!flying) if (!m_flying)
{ {
// we are on a surface // we are on a surface
if (ctz.Z > 0f) if (ctz.Z > 0f)
@ -1361,7 +1378,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
} }
else // ie not colliding else // ie not colliding
{ {
if (flying || hoverPIDActive) //(!m_iscolliding && flying) if (m_flying || hoverPIDActive) //(!m_iscolliding && flying)
{ {
// we're in mid air suspended // we're in mid air suspended
vec.X += (ctz.X - vel.X) * (PID_D); vec.X += (ctz.X - vel.X) * (PID_D);
@ -1397,13 +1414,13 @@ namespace OpenSim.Region.PhysicsModule.ubOde
breakfactor = m_mass; breakfactor = m_mass;
vec.X -= breakfactor * vel.X; vec.X -= breakfactor * vel.X;
vec.Y -= breakfactor * vel.Y; vec.Y -= breakfactor * vel.Y;
if (flying) if (m_flying)
vec.Z -= 0.5f * breakfactor * vel.Z; vec.Z -= 0.5f * breakfactor * vel.Z;
else else
vec.Z -= .16f* m_mass * vel.Z; vec.Z -= .16f* m_mass * vel.Z;
} }
if (flying || hoverPIDActive) if (m_flying || hoverPIDActive)
{ {
vec.Z -= m_parent_scene.gravityz * m_mass; vec.Z -= m_parent_scene.gravityz * m_mass;

View File

@ -345,6 +345,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body) if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
&& !rootPrim.m_isSelected && !rootPrim.m_disabled) && !rootPrim.m_isSelected && !rootPrim.m_disabled)
d.BodyEnable(rootPrim.Body); d.BodyEnable(rootPrim.Body);
break; break;
case Vehicle.LINEAR_FRICTION_TIMESCALE: case Vehicle.LINEAR_FRICTION_TIMESCALE:
if (pValue < m_timestep) pValue = m_timestep; if (pValue < m_timestep) pValue = m_timestep;

View File

@ -1043,6 +1043,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.BodySetLinearVel(Body, 0, 0, 0); // stop it d.BodySetLinearVel(Body, 0, 0, 0); // stop it
d.BodySetAngularVel(Body, 0, 0, 0); d.BodySetAngularVel(Body, 0, 0, 0);
} }
if(prim_geom != IntPtr.Zero)
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
disableBodySoft(); // stop collisions disableBodySoft(); // stop collisions
UnSubscribeEvents(); UnSubscribeEvents();
@ -1240,7 +1241,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
SentEmptyCollisionsEvent = true; SentEmptyCollisionsEvent = true;
// _parent_scene.RemoveCollisionEventReporting(this); // _parent_scene.RemoveCollisionEventReporting(this);
} }
else if(Body == IntPtr.Zero || d.BodyIsEnabled(Body)) else if(Body == IntPtr.Zero || (d.BodyIsEnabled(Body) && m_bodydisablecontrol >= 0 ))
{ {
SentEmptyCollisionsEvent = false; SentEmptyCollisionsEvent = false;
CollisionEventsThisFrame.Clear(); CollisionEventsThisFrame.Clear();
@ -1847,8 +1848,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
ApplyCollisionCatFlags(); ApplyCollisionCatFlags();
_zeroFlag = true; _zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
resetCollisionAccounting(); resetCollisionAccounting();
@ -2900,6 +2901,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !m_disabled) if (Body != IntPtr.Zero && !m_disabled)
{ {
_zeroFlag = true; _zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
@ -2933,6 +2935,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (!d.BodyIsEnabled(Body)) if (!d.BodyIsEnabled(Body))
{ {
_zeroFlag = true; _zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
@ -2947,6 +2950,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{ {
_zeroFlag = true; _zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
@ -3012,6 +3016,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{ {
_zeroFlag = true; _zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
@ -3070,6 +3075,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{ {
_zeroFlag = true; _zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
@ -3312,8 +3318,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled) if (m_disabled)
enableBodySoft(); enableBodySoft();
else if (!d.BodyIsEnabled(Body)) else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
}
} }
m_torque = newtorque; m_torque = newtorque;
} }
@ -3323,8 +3331,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde
{ {
m_force = force; m_force = force;
if (!m_isSelected && !m_outbounds && Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) if (!m_isSelected && !m_outbounds && Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
}
private void changeAddForce(Vector3 theforce) private void changeAddForce(Vector3 theforce)
{ {
@ -3339,9 +3350,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled) if (m_disabled)
enableBodySoft(); enableBodySoft();
else if (!d.BodyIsEnabled(Body)) else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
}
m_collisionscore = 0; m_collisionscore = 0;
} }
} }
@ -3359,9 +3373,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled) if (m_disabled)
enableBodySoft(); enableBodySoft();
else if (!d.BodyIsEnabled(Body)) else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
} }
} }
}
m_collisionscore = 0; m_collisionscore = 0;
} }
} }
@ -3382,7 +3399,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled) if (m_disabled)
enableBodySoft(); enableBodySoft();
else if (!d.BodyIsEnabled(Body)) else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
}
d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z); d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
} }
//resetCollisionAccounting(); //resetCollisionAccounting();
@ -3406,7 +3426,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled) if (m_disabled)
enableBodySoft(); enableBodySoft();
else if (!d.BodyIsEnabled(Body)) else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body); d.BodyEnable(Body);
}
d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z); d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
} }
//resetCollisionAccounting(); //resetCollisionAccounting();
@ -3571,8 +3594,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.BodySetAngularVel(Body,0f,0f,0f); d.BodySetAngularVel(Body,0f,0f,0f);
d.BodySetLinearVel(Body,0f,0f,0f); d.BodySetLinearVel(Body,0f,0f,0f);
_zeroFlag = true; _zeroFlag = true;
d.BodySetAutoDisableSteps(Body, 1);
d.BodyEnable(Body); d.BodyEnable(Body);
m_bodydisablecontrol = -4; m_bodydisablecontrol = -3;
} }
if(m_bodydisablecontrol < 0) if(m_bodydisablecontrol < 0)
@ -3741,13 +3765,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
public void UpdatePositionAndVelocity(int frame) public void UpdatePositionAndVelocity(int frame)
{ {
if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero) if (_parent == null && !m_isSelected && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
{ {
bool bodyenabled = d.BodyIsEnabled(Body);
if(m_bodydisablecontrol < 0) if(m_bodydisablecontrol < 0)
return; return;
bool bodyenabled = d.BodyIsEnabled(Body);
if (bodyenabled || !_zeroFlag) if (bodyenabled || !_zeroFlag)
{ {
bool lastZeroFlag = _zeroFlag; bool lastZeroFlag = _zeroFlag;

View File

@ -203,8 +203,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
private float metersInSpace = 25.6f; private float metersInSpace = 25.6f;
private float m_timeDilation = 1.0f; private float m_timeDilation = 1.0f;
private DateTime m_lastframe; private double m_lastframe;
private DateTime m_lastMeshExpire; private double m_lastMeshExpire;
public float gravityx = 0f; public float gravityx = 0f;
public float gravityy = 0f; public float gravityy = 0f;
@ -481,7 +481,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision); contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision);
geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity); geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable); // bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
physics_logging = physicsconfig.GetBoolean("physics_logging", false); physics_logging = physicsconfig.GetBoolean("physics_logging", false);
physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
@ -629,8 +629,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
staticPrimspaceOffRegion[i] = newspace; staticPrimspaceOffRegion[i] = newspace;
} }
m_lastframe = DateTime.UtcNow; m_lastframe = Util.GetTimeStamp();
m_lastMeshExpire = m_lastframe; m_lastMeshExpire = m_lastframe;
step_time = -1;
} }
internal void waitForSpaceUnlock(IntPtr space) internal void waitForSpaceUnlock(IntPtr space)
@ -952,8 +953,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
SharedTmpcontact.surface.bounce = bounce; SharedTmpcontact.surface.bounce = bounce;
d.ContactGeom altContact = new d.ContactGeom(); d.ContactGeom altContact = new d.ContactGeom();
bool useAltcontact = false; bool useAltcontact;
bool noskip = true; bool noskip;
if(dop1ava || dop2ava) if(dop1ava || dop2ava)
smoothMesh = false; smoothMesh = false;
@ -1000,7 +1001,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
Joint = CreateContacJoint(ref altContact,smoothMesh); Joint = CreateContacJoint(ref altContact,smoothMesh);
else else
Joint = CreateContacJoint(ref curContact,smoothMesh); Joint = CreateContacJoint(ref curContact,smoothMesh);
if (Joint == IntPtr.Zero) if (Joint == IntPtr.Zero)
break; break;
@ -1626,6 +1626,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
} }
m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count); m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count);
} }
m_lastframe = Util.GetTimeStamp() + 0.5;
step_time = -0.5f;
} }
/// <summary> /// <summary>
@ -1639,13 +1641,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
/// <returns></returns> /// <returns></returns>
public override float Simulate(float reqTimeStep) public override float Simulate(float reqTimeStep)
{ {
DateTime now = DateTime.UtcNow; double now = Util.GetTimeStamp();
TimeSpan timedif = now - m_lastframe; double timeStep = now - m_lastframe;
float timeStep = (float)timedif.TotalSeconds;
m_lastframe = now; m_lastframe = now;
// acumulate time so we can reduce error // acumulate time so we can reduce error
step_time += timeStep; step_time += (float)timeStep;
if (step_time < HalfOdeStep) if (step_time < HalfOdeStep)
return 0; return 0;
@ -1854,14 +1855,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
} }
} }
timedif = now - m_lastMeshExpire;
if (timedif.Seconds > 10)
{
mesher.ExpireReleaseMeshs();
m_lastMeshExpire = now;
}
// information block for in debug breakpoint only // information block for in debug breakpoint only
/* /*
int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
@ -1941,7 +1934,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
// if we lag too much skip frames // if we lag too much skip frames
m_timeDilation = 0.0f; m_timeDilation = 0.0f;
step_time = 0; step_time = 0;
m_lastframe = DateTime.UtcNow; // skip also the time lost m_lastframe = Util.GetTimeStamp(); // skip also the time lost
} }
else else
{ {
@ -1949,6 +1942,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_timeDilation > 1) if (m_timeDilation > 1)
m_timeDilation = 1; m_timeDilation = 1;
} }
if (m_timeDilation == 1 && now - m_lastMeshExpire > 30)
{
mesher.ExpireReleaseMeshs();
m_lastMeshExpire = now;
}
} }
return fps; return fps;

View File

@ -3534,9 +3534,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot) public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
Util.FireAndForget(x =>
{
if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
return; return;
@ -3559,7 +3556,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
} }
List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param, atRoot); Util.FireAndForget(x =>
{
Quaternion wrot = rot;
wrot.Normalize();
List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, wrot, vel, param, atRoot);
// If either of these are null, then there was an unknown error. // If either of these are null, then there was an unknown error.
if (new_groups == null) if (new_groups == null)
@ -3596,9 +3598,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
} }
} }
// Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
} }
}, null, "LSL_Api.doObjectRez"); }, null, "LSL_Api.doObjectRez");
//ScriptSleep((int)((groupmass * velmag) / 10)); //ScriptSleep((int)((groupmass * velmag) / 10));

View File

@ -123,6 +123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams, string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams,
bool blend, int disp, int timer, int alpha, int face); bool blend, int disp, int timer, int alpha, int face);
string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer); string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer);
string osSetDynamicTextureDataFace(string dynamicID, string contentType, string data, string extraParams, int timer, int face);
string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
int timer, int alpha); int timer, int alpha);
string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams, string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams,
@ -143,8 +144,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
void osSetParcelSIPAddress(string SIPAddress); void osSetParcelSIPAddress(string SIPAddress);
// Avatar Info Commands // Avatar Info Commands
string osGetAgentIP(string agent);
LSL_List osGetAgents(); LSL_List osGetAgents();
string osGetAgentIP(string agent);
// Teleport commands // Teleport commands
void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
@ -222,10 +223,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
string osDrawLine(string drawList, int endX, int endY); string osDrawLine(string drawList, int endX, int endY);
string osDrawText(string drawList, string text); string osDrawText(string drawList, string text);
string osDrawEllipse(string drawList, int width, int height); string osDrawEllipse(string drawList, int width, int height);
string osDrawFilledEllipse(string drawList, int width, int height);
string osDrawRectangle(string drawList, int width, int height); string osDrawRectangle(string drawList, int width, int height);
string osDrawFilledRectangle(string drawList, int width, int height); string osDrawFilledRectangle(string drawList, int width, int height);
string osDrawPolygon(string drawList, LSL_List x, LSL_List y); string osDrawPolygon(string drawList, LSL_List x, LSL_List y);
string osDrawFilledPolygon(string drawList, LSL_List x, LSL_List y); string osDrawFilledPolygon(string drawList, LSL_List x, LSL_List y);
string osDrawResetTransform(string drawList);
string osDrawRotationTransform(string drawList, LSL_Float x);
string osDrawScaleTransform(string drawList, LSL_Float x, LSL_Float y);
string osDrawTranslationTransform(string drawList, LSL_Float x, LSL_Float y);
string osSetFontName(string drawList, string fontName); string osSetFontName(string drawList, string fontName);
string osSetFontSize(string drawList, int fontSize); string osSetFontSize(string drawList, int fontSize);
string osSetPenSize(string drawList, int penSize); string osSetPenSize(string drawList, int penSize);
@ -389,6 +395,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb); void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb);
LSL_List osGetAvatarList(); LSL_List osGetAvatarList();
LSL_List osGetNPCList();
LSL_String osUnixTimeToTimestamp(long time); LSL_String osUnixTimeToTimestamp(long time);

View File

@ -697,7 +697,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int PARCEL_DETAILS_GROUP = 3; public const int PARCEL_DETAILS_GROUP = 3;
public const int PARCEL_DETAILS_AREA = 4; public const int PARCEL_DETAILS_AREA = 4;
public const int PARCEL_DETAILS_ID = 5; public const int PARCEL_DETAILS_ID = 5;
public const int PARCEL_DETAILS_SEE_AVATARS = 6; // not implemented public const int PARCEL_DETAILS_SEE_AVATARS = 6;
public const int PARCEL_DETAILS_ANY_AVATAR_SOUNDS = 7;
public const int PARCEL_DETAILS_GROUP_SOUNDS = 8;
//osSetParcelDetails //osSetParcelDetails
public const int PARCEL_DETAILS_CLAIMDATE = 10; public const int PARCEL_DETAILS_CLAIMDATE = 10;

View File

@ -153,6 +153,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osSetDynamicTextureData(dynamicID, contentType, data, extraParams, timer); return m_OSSL_Functions.osSetDynamicTextureData(dynamicID, contentType, data, extraParams, timer);
} }
public string osSetDynamicTextureDataFace(string dynamicID, string contentType, string data, string extraParams,
int timer, int face)
{
return m_OSSL_Functions.osSetDynamicTextureDataFace(dynamicID, contentType, data, extraParams, timer, face);
}
public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
int timer, int alpha) int timer, int alpha)
{ {
@ -271,17 +277,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_OSSL_Functions.osTeleportOwner(position, lookat); m_OSSL_Functions.osTeleportOwner(position, lookat);
} }
// Avatar info functions
public string osGetAgentIP(string agent)
{
return m_OSSL_Functions.osGetAgentIP(agent);
}
public LSL_List osGetAgents() public LSL_List osGetAgents()
{ {
return m_OSSL_Functions.osGetAgents(); return m_OSSL_Functions.osGetAgents();
} }
public string osGetAgentIP(string agent)
{
return m_OSSL_Functions.osGetAgentIP(agent);
}
// Animation Functions // Animation Functions
public void osAvatarPlayAnimation(string avatar, string animation) public void osAvatarPlayAnimation(string avatar, string animation)
@ -355,6 +360,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osDrawEllipse(drawList, width, height); return m_OSSL_Functions.osDrawEllipse(drawList, width, height);
} }
public string osDrawFilledEllipse(string drawList, int width, int height)
{
return m_OSSL_Functions.osDrawFilledEllipse(drawList, width, height);
}
public string osDrawRectangle(string drawList, int width, int height) public string osDrawRectangle(string drawList, int width, int height)
{ {
return m_OSSL_Functions.osDrawRectangle(drawList, width, height); return m_OSSL_Functions.osDrawRectangle(drawList, width, height);
@ -375,6 +385,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osDrawFilledPolygon(drawList, x, y); return m_OSSL_Functions.osDrawFilledPolygon(drawList, x, y);
} }
public string osDrawResetTransform(string drawList)
{
return m_OSSL_Functions.osDrawResetTransform(drawList);
}
public string osDrawRotationTransform(string drawList, LSL_Float x)
{
return m_OSSL_Functions.osDrawRotationTransform(drawList, x);
}
public string osDrawScaleTransform(string drawList, LSL_Float x, LSL_Float y)
{
return m_OSSL_Functions.osDrawScaleTransform(drawList, x, y);
}
public string osDrawTranslationTransform(string drawList, LSL_Float x, LSL_Float y)
{
return m_OSSL_Functions.osDrawTranslationTransform(drawList, x, y);
}
public string osSetFontSize(string drawList, int fontSize) public string osSetFontSize(string drawList, int fontSize)
{ {
return m_OSSL_Functions.osSetFontSize(drawList, fontSize); return m_OSSL_Functions.osSetFontSize(drawList, fontSize);
@ -399,6 +429,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{ {
return m_OSSL_Functions.osSetPenColor(drawList, color); return m_OSSL_Functions.osSetPenColor(drawList, color);
} }
// Deprecated // Deprecated
public string osSetPenColour(string drawList, string colour) public string osSetPenColour(string drawList, string colour)
{ {
@ -1010,6 +1041,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osGetAvatarList(); return m_OSSL_Functions.osGetAvatarList();
} }
public LSL_List osGetNPCList()
{
return m_OSSL_Functions.osGetNPCList();
}
public LSL_String osUnixTimeToTimestamp(long time) public LSL_String osUnixTimeToTimestamp(long time)
{ {
return m_OSSL_Functions.osUnixTimeToTimestamp(time); return m_OSSL_Functions.osUnixTimeToTimestamp(time);

View File

@ -39,7 +39,6 @@ using OMV_Quaternion = OpenMetaverse.Quaternion;
namespace OpenSim.Region.ScriptEngine.Shared namespace OpenSim.Region.ScriptEngine.Shared
{ {
[Serializable]
public partial class LSL_Types public partial class LSL_Types
{ {
// Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain
@ -526,7 +525,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
} }
[Serializable] [Serializable]
public class list public class list: MarshalByRefObject
{ {
private object[] m_data; private object[] m_data;

View File

@ -109,6 +109,7 @@ namespace OpenSim.Tests.Common
public bool IsLandPrimCountTainted() { return false; } public bool IsLandPrimCountTainted() { return false; }
public bool IsForcefulBansAllowed() { return false; } public bool IsForcefulBansAllowed() { return false; }
public void UpdateLandObject(int localID, LandData data) {} public void UpdateLandObject(int localID, LandData data) {}
public void SendParcelsOverlay(IClientAPI client) {}
public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) {} public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) {}
public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) {} public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) {}
public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) {} public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) {}

View File

@ -118,8 +118,7 @@ namespace OpenSim.Tests.Stress
so.UUID, so.UUID,
m_tests.Vrm.GetContentType(), m_tests.Vrm.GetContentType(),
string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text), string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text),
"", "");
0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));

View File

@ -1,349 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>OpenMetaverse.StructuredData</name>
</assembly>
<members>
<member name="T:OpenMetaverse.StructuredData.OSDType">
<summary>
</summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Unknown">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Boolean">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Integer">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Real">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.String">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.UUID">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Date">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.URI">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Binary">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Map">
<summary></summary>
</member>
<member name="F:OpenMetaverse.StructuredData.OSDType.Array">
<summary></summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDException">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSD">
<summary>
</summary>
</member>
<member name="M:OpenMetaverse.StructuredData.OSD.SerializeMembers(System.Object)">
<summary>
Uses reflection to create an SDMap from all of the SD
serializable types in an object
</summary>
<param name="obj">Class or struct containing serializable types</param>
<returns>An SDMap holding the serialized values from the
container object</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSD.DeserializeMembers(System.Object@,OpenMetaverse.StructuredData.OSDMap)">
<summary>
Uses reflection to deserialize member variables in an object from
an SDMap
</summary>
<param name="obj">Reference to an object to fill with deserialized
values</param>
<param name="serialized">Serialized values to put in the target
object</param>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDBoolean">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDInteger">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDReal">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDString">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDUUID">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDDate">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDUri">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDBinary">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDMap">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDArray">
<summary>
</summary>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDParser">
<summary>
</summary>
<summary>
</summary>
<summary>
</summary>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDBinary(System.Byte[])">
<summary>
Deserializes binary LLSD
</summary>
<param name="binaryData">Serialized data</param>
<returns>OSD containting deserialized data</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDBinary(System.IO.Stream)">
<summary>
Deserializes binary LLSD
</summary>
<param name="stream">Stream to read the data from</param>
<returns>OSD containting deserialized data</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SerializeLLSDBinary(OpenMetaverse.StructuredData.OSD)">
<summary>
Serializes OSD to binary format. It does no prepend header
</summary>
<param name="osd">OSD to serialize</param>
<returns>Serialized data</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SerializeLLSDBinary(OpenMetaverse.StructuredData.OSD,System.Boolean)">
<summary>
Serializes OSD to binary format
</summary>
<param name="osd">OSD to serialize</param>
<param name="prependHeader"></param>
<returns>Serialized data</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SerializeLLSDBinaryStream(OpenMetaverse.StructuredData.OSD)">
<summary>
Serializes OSD to binary format. It does no prepend header
</summary>
<param name="data">OSD to serialize</param>
<returns>Serialized data</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SerializeLLSDBinaryStream(OpenMetaverse.StructuredData.OSD,System.Boolean)">
<summary>
Serializes OSD to binary format
</summary>
<param name="data">OSD to serialize</param>
<param name="prependHeader"></param>
<returns>Serialized data</returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SkipWhiteSpace(System.IO.Stream)">
<summary>
</summary>
<param name="stream"></param>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.FindByte(System.IO.Stream,System.Byte)">
<summary>
</summary>
<param name="stream"></param>
<param name="toFind"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.FindString(System.IO.Stream,System.String)">
<summary>
</summary>
<param name="stream"></param>
<param name="toFind"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.ConsumeBytes(System.IO.Stream,System.Int32)">
<summary>
</summary>
<param name="stream"></param>
<param name="consumeBytes"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.NetworkToHostInt(System.Byte[])">
<summary>
</summary>
<param name="binaryNetEnd"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.NetworkToHostDouble(System.Byte[])">
<summary>
</summary>
<param name="binaryNetEnd"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.HostToNetworkIntBytes(System.Int32)">
<summary>
</summary>
<param name="intHostEnd"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDNotationElement(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.PeekAndSkipWhitespace(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.ReadAndSkipWhitespace(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.GetLengthInBrackets(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.GetStringDelimitedBy(System.IO.StringReader,System.Char)">
<summary>
</summary>
<param name="reader"></param>
<param name="delimiter"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.BufferCharactersEqual(System.IO.StringReader,System.Char[],System.Int32)">
<summary>
</summary>
<param name="reader"></param>
<param name="buffer"></param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.UnescapeCharacter(System.String,System.Char)">
<summary>
</summary>
<param name="s"></param>
<param name="c"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.EscapeCharacter(System.String,System.Char)">
<summary>
</summary>
<param name="s"></param>
<param name="c"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDXml(System.Byte[])">
<summary>
</summary>
<param name="xmlData"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDXml(System.String)">
<summary>
</summary>
<param name="xmlData"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDXml(System.Xml.XmlTextReader)">
<summary>
</summary>
<param name="xmlData"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SerializeLLSDXmlBytes(OpenMetaverse.StructuredData.OSD)">
<summary>
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SerializeLLSDXmlString(OpenMetaverse.StructuredData.OSD)">
<summary>
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.SerializeLLSDXmlElement(System.Xml.XmlTextWriter,OpenMetaverse.StructuredData.OSD)">
<summary>
</summary>
<param name="writer"></param>
<param name="data"></param>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.TryValidateLLSDXml(System.Xml.XmlTextReader,System.String@)">
<summary>
</summary>
<param name="xmlData"></param>
<param name="error"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.ParseLLSDXmlElement(System.Xml.XmlTextReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
</members>
</doc>

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1464,13 +1464,21 @@
[Trees] [Trees]
; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying ; enable the trees module. default true
; default is false enabled = true
; active_trees allows module to change its trees in time.
; some will be deleted, others created and rest may grow
; default is false. You can change it with console comand tree active true | false later
active_trees = false active_trees = false
; the trees change execution time rate (in ms)
update_rate = 1000
; Density of tree population ; allow the trees to grow.
tree_density = 1000.0 ; DANGER
; this option causes high network use on the order of
; NumberOfTrees * NumberAvatars * 1000 / update_rate udp packets per second
allowGrow = false
[VectorRender] [VectorRender]
; the font to use for rendering text (default: Arial) ; the font to use for rendering text (default: Arial)

View File

@ -31,7 +31,7 @@
; higher threat level OSSL functions, as detailed later on. ; higher threat level OSSL functions, as detailed later on.
OSFunctionThreatLevel = VeryLow OSFunctionThreatLevel = VeryLow
; Each of the OSSL functions can be enabled or disabled individually. ; Some of the OSSL functions can be enabled or disabled individually.
; To disable, set the value to 'false'. ; To disable, set the value to 'false'.
; To enable for everyone, set the value to 'true'. ; To enable for everyone, set the value to 'true'.
; To enable for individuals or groups, set it to a comma separated list. This checks ; To enable for individuals or groups, set it to a comma separated list. This checks
@ -45,12 +45,10 @@
; "PARCEL_OWNER" -- enable for parcel owner ; "PARCEL_OWNER" -- enable for parcel owner
; "PARCEL_GROUP_MEMBER" -- enable for any member of the parcel group ; "PARCEL_GROUP_MEMBER" -- enable for any member of the parcel group
; uuid -- enable for specified ID (may be avatar or group ID) ; uuid -- enable for specified ID (may be avatar or group ID)
; from this we can also create macros that can be include in the list as
; ${XEngine|macroname} see examples below
; The OSSL function name is prepended with "Allow_" and it checks against ; parcel macros
; the owners of the containing prim. There can also be entries beginning with
; 'Creators_". The 'Creators_" parameters can only be a list of UUIDs and it is
; checked against the creator of the script itself.
; Allowing ossl functions for anyone owning a parcel can be dangerous especially if ; Allowing ossl functions for anyone owning a parcel can be dangerous especially if
; a region is selling or otherwise giving away parcel ownership. By default, parcel ; a region is selling or otherwise giving away parcel ownership. By default, parcel
; ownership or group membership does not enable OSSL functions. Uncomment the ; ownership or group membership does not enable OSSL functions. Uncomment the
@ -62,49 +60,31 @@
; osslParcelO = "PARCEL_OWNER," ; osslParcelO = "PARCEL_OWNER,"
; osslParcelOG = "PARCEL_GROUP_MEMBER,PARCEL_OWNER," ; osslParcelOG = "PARCEL_GROUP_MEMBER,PARCEL_OWNER,"
; There are a block of functions for creating and controlling NPCs. ; NPC macros
; These can be mis-used so limit use to those you can trust. ; These can be mis-used so limit use to those you can trust.
osslNPC = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER osslNPC = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
; The OSSL function name is prepended with "Allow_" and it checks against
; the owners of the containing prim. There can also be entries beginning with
; 'Creators_". The 'Creators_" parameters can only be a list of UUIDs and it is
; checked against the creator of the script itself.
; *************************************************
; ThreatLevel None ; ThreatLevel None
Allow_osDrawEllipse = true
Allow_osDrawFilledPolygon = true
Allow_osDrawFilledRectangle = true
Allow_osDrawImage = true
Allow_osDrawLine = true
Allow_osDrawPolygon = true
Allow_osDrawRectangle = true
Allow_osDrawText = true
Allow_osGetAgents = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetAgents = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetAvatarList = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetAvatarList = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetCurrentSunHour = true
Allow_osGetGender = true Allow_osGetGender = true
Allow_osGetHealth = true Allow_osGetHealth = true
Allow_osGetHealRate = true Allow_osGetHealRate = true
Allow_osGetInventoryDesc = true Allow_osGetNPCList = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetMapTexture = true
Allow_osGetRegionSize = true
Allow_osGetRezzingObject = true Allow_osGetRezzingObject = true
Allow_osGetSunParam = true
Allow_osGetTerrainHeight = true
Allow_osIsNpc = true
Allow_osIsUUID = true
Allow_osList2Double = true
Allow_osMax = true
Allow_osMin = true
Allow_osMovePen = true
Allow_osNpcGetOwner = ${XEngine|osslNPC} Allow_osNpcGetOwner = ${XEngine|osslNPC}
Allow_osParseJSON = true Allow_osParseJSON = true
Allow_osParseJSONNew = true Allow_osParseJSONNew = true
Allow_osSetFontName = true
Allow_osSetFontSize = true
Allow_osSetPenCap = true
Allow_osSetPenColor = true
Allow_osSetPenSize = true
Allow_osSetSunParam = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetSunParam = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osTeleportOwner = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osTeleportOwner = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osWindActiveModelPluginName = true Allow_osWindActiveModelPluginName = true
Allow_osCheckODE = true ; Here for completeness. This function cannot be turned off
; ThreatLevel Nuisance ; ThreatLevel Nuisance
Allow_osSetEstateSunSettings = ESTATE_MANAGER,ESTATE_OWNER Allow_osSetEstateSunSettings = ESTATE_MANAGER,ESTATE_OWNER
@ -114,11 +94,11 @@
Allow_osEjectFromGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osEjectFromGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osForceBreakAllLinks = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceBreakAllLinks = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osForceBreakLink = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceBreakLink = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetDrawStringSize = true
Allow_osGetWindParam = true Allow_osGetWindParam = true
Allow_osInviteToGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osInviteToGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osReplaceString = true Allow_osReplaceString = true
Allow_osSetDynamicTextureData = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetDynamicTextureData = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osSetDynamicTextureDataFace = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osSetDynamicTextureDataBlend = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetDynamicTextureDataBlend = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osSetDynamicTextureDataBlendFace = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetDynamicTextureDataBlendFace = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osSetDynamicTextureURL = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetDynamicTextureURL = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
@ -171,7 +151,6 @@
Allow_osForceCreateLink = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceCreateLink = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osForceDropAttachment = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceDropAttachment = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osForceDropAttachmentAt = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceDropAttachmentAt = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetAgentIP = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetLinkPrimitiveParams = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetLinkPrimitiveParams = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetPhysicsEngineType = true Allow_osGetPhysicsEngineType = true
Allow_osGetPrimitiveParams = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetPrimitiveParams = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
@ -238,3 +217,49 @@
Allow_osTeleportAgent = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osTeleportAgent = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osTeleportObject = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osTeleportObject = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
; funtions ThreatLevel Severe with additional internal restrictions
Allow_osGetAgentIP = true ; always restricted to Administrators (true or false to disable)
; available funtions out of Threat level control (for reference only)
; Allow_osClearInertia = true
; Allow_osCheckODE = true
; Allow_osCollisionSound = true
; Allow_osDrawEllipse = true
; Allow_osDrawFilledEllipse = true
; Allow_osDrawFilledPolygon = true
; Allow_osDrawFilledRectangle = true
; Allow_osDrawResetTransform = true
; Allow_osDrawRotationTransform = true
; Allow_osDrawScaleTransform = true
; Allow_osDrawTranslationTransform = true
; Allow_osDrawImage = true
; Allow_osDrawLine = true
; Allow_osDrawPolygon = true
; Allow_osDrawRectangle = true
; Allow_osDrawText = true
; Allow_osGetCurrentSunHour = true
; Allow_osGetPhysicsEngineName = true
; Allow_osGetInertiaData = true
; Allow_osGetInventoryDesc = true
; Allow_osGetLinkNumber = true
; Allow_osGetMapTexture = true
; Allow_osGetRegionSize = true
; Allow_osGetSunParam = true
; Allow_osGetTerrainHeight = true
; Allow_osGetDrawStringSize = true
; Allow_osIsNpc = true
; Allow_osIsUUID = true
; Allow_osList2Double = true
; Allow_osMax = true
; Allow_osMin = true
; Allow_osMovePen = true
; Allow_osSetInertia = true
; Allow_osSetInertiaAsBox = true
; Allow_osSetInertiaAsSphere = true
; Allow_osSetInertiaAsCylinder = true
; Allow_osSetFontName = true
; Allow_osSetFontSize = true
; Allow_osSetPenCap = true
; Allow_osSetPenColor = true
; Allow_osSetPenSize = true
; Allow_osVolumeDetect = true

Binary file not shown.

Binary file not shown.