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);
if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float,
Utils.EnUsCulture.NumberFormat, out value))
Culture.NumberFormatInfo, out value))
return value;
else
throw new LLSDParseException("Failed to parse double value type");

View File

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

View File

@ -64,25 +64,25 @@ namespace OpenSim.Framework
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)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
writer.WriteEndElement();
}
private void XWVector4(string name, Vector4 quat)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
writer.WriteEndElement();
}

View File

@ -216,6 +216,27 @@ namespace OpenSim.Framework
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>
/// Reapply the prioritization function to each of the updates currently
/// stored in the priority queues.

View File

@ -156,12 +156,14 @@ namespace OpenSim.Framework
public static readonly int MAX_THREADPOOL_LEVEL = 3;
public static double TimeStampClockPeriodMS;
public static double TimeStampClockPeriod;
static Util()
{
LogThreadPool = 0;
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));
}
@ -2221,9 +2223,9 @@ namespace OpenSim.Framework
// might have gotten an oversized array even after the string trim
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 )
{
while(cut > 0 && (data[cut] & 0xc0) != 0xc0)
@ -2325,7 +2327,7 @@ namespace OpenSim.Framework
if (data.Length > MaxLength)
{
int cut = MaxLength -1 ;
int cut = MaxLength - 1 ;
if((data[cut] & 0x80 ) != 0 )
{
while(cut > 0 && (data[cut] & 0xc0) != 0xc0)
@ -2967,9 +2969,9 @@ namespace OpenSim.Framework
/// <returns></returns>
public static Int32 EnvironmentTickCount()
{
double now = GetTimeStampMS();
return (int)now;
return Environment.TickCount & EnvironmentTickCountMask;
}
const Int32 EnvironmentTickCountMask = 0x3fffffff;
/// <summary>
@ -2994,8 +2996,7 @@ namespace OpenSim.Framework
/// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
{
double now = GetTimeStampMS();
return EnvironmentTickCountSubtract((int)now, prevValue);
return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue);
}
// 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
// using the time resolution avaiable to StopWatch
public static double GetTimeStamp()
{
return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriod;
}
public static double GetTimeStampMS()
{
return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriodMS;

View File

@ -220,7 +220,7 @@ namespace OpenSim.Region.ClientStack.Linden
PollServiceMeshEventArgs 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)
{
m_scene = scene;
m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
m_throttler = new MeshCapsDataThrottler(100000);
// x is request id, y is userid
HasEvents = (x, y) =>
{
lock (responses)
{
bool ret = m_throttler.hasEvents(x, responses);
m_throttler.ProcessTime();
return ret;
}
@ -271,8 +270,8 @@ namespace OpenSim.Region.ClientStack.Linden
}
finally
{
m_throttler.ProcessTime();
responses.Remove(x);
m_throttler.PassTime();
}
}
};
@ -285,6 +284,7 @@ namespace OpenSim.Region.ClientStack.Linden
reqinfo.request = y;
m_queue.Enqueue(reqinfo);
m_throttler.PassTime();
};
// 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
{
private double lastTimeElapsed = 0;
private double BytesSent = 0;
private volatile int currenttime = 0;
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)
public MeshCapsDataThrottler(int pBytes)
{
if(pBytes < 10000)
pBytes = 10000;
ThrottleBytes = pBytes;
if(ThrottleBytes < 10000)
ThrottleBytes = 10000;
lastTimeElapsed = Util.EnvironmentTickCount();
Throttle = ThrottleOutPacketType.Asset;
m_scene = pScene;
User = puser;
lastTimeElapsed = Util.GetTimeStampMS();
}
public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
@ -470,46 +464,22 @@ namespace OpenSim.Region.ClientStack.Linden
return haskey;
}
public void ProcessTime()
public void PassTime()
{
PassTime();
}
private void PassTime()
{
currenttime = Util.EnvironmentTickCount();
int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
if (timeElapsed >= 100)
double currenttime = Util.GetTimeStampMS();
double timeElapsed = currenttime - lastTimeElapsed;
if(timeElapsed < 50.0)
return;
int add = (int)(ThrottleBytes * timeElapsed * 0.001);
if (add >= 1000)
{
lastTimeElapsed = currenttime;
BytesSent -= (ThrottleBytes * timeElapsed / 1000);
BytesSent -= add;
if (BytesSent < 0) BytesSent = 0;
}
}
private void AlterThrottle(int setting, ScenePresence p)
{
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();
}
public int ThrottleBytes;
}
}
}

View File

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

View File

@ -4137,6 +4137,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Vector3 mypos = Vector3.Zero;
ScenePresence mysp = (ScenePresence)SceneAgent;
bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
// we should have a presence
if(mysp == null)
return;
@ -4151,8 +4152,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
while (maxUpdatesBytes > 0)
{
lock (m_entityUpdates.SyncRoot)
{
if(orderedDequeue)
{
if (!m_entityUpdates.TryOrderedDequeue(out update, out timeinqueue))
break;
}
else
{
if (!m_entityUpdates.TryDequeue(out update, out timeinqueue))
break;
}
}
PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
@ -4850,6 +4861,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
// new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
EntityUpdate iupdate;
Int32 timeinqueue; // this is just debugging code & can be dropped later
@ -4857,8 +4869,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
while (maxUpdateBytes > 0)
{
lock (m_entityProps.SyncRoot)
{
if(orderedDequeue)
{
if (!m_entityProps.TryOrderedDequeue(out iupdate, out timeinqueue))
break;
}
else
{
if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
break;
}
}
ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
if (update.SendFamilyProps)
@ -5526,6 +5548,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion
#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)
{
@ -5616,11 +5658,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
pos += 12;
// Velocity
ClampVectorForUint(ref velocity, 128f);
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.Z, -128.0f, 128.0f), data, pos); pos += 2;
// Acceleration
ClampVectorForUint(ref acceleration, 64f);
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.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;
// 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.Y, -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.JointType = 0;
update.Material = part.Material;
update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
/*
if (data.ParentGroup.IsAttachment)
{
@ -5832,8 +5876,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.TextureAnim = part.TextureAnimation ?? Utils.EmptyBytes;
update.TextureEntry = part.Shape.TextureEntry ?? Utils.EmptyBytes;
update.Scale = part.Shape.Scale;
update.Text = Util.StringToBytes256(part.Text);
update.MediaURL = Util.StringToBytes256(part.MediaUrl);
update.Text = Util.StringToBytes(part.Text, 255);
update.MediaURL = Util.StringToBytes(part.MediaUrl, 255);
#region PrimFlags
@ -6234,20 +6278,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name='x'></param>
private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
{
float vdelta = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis);
if((vdelta > VDELTA))
return true;
if(Math.Abs(x.CameraCenter.X - m_thisAgentUpdateArgs.CameraCenter.X) > VDELTA ||
Math.Abs(x.CameraCenter.Y - m_thisAgentUpdateArgs.CameraCenter.Y) > VDELTA ||
Math.Abs(x.CameraCenter.Z - m_thisAgentUpdateArgs.CameraCenter.Z) > VDELTA ||
vdelta = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter);
if((vdelta > VDELTA))
return true;
Math.Abs(x.CameraAtAxis.X - m_thisAgentUpdateArgs.CameraAtAxis.X) > VDELTA ||
Math.Abs(x.CameraAtAxis.Y - m_thisAgentUpdateArgs.CameraAtAxis.Y) > VDELTA ||
// Math.Abs(x.CameraAtAxis.Z - m_thisAgentUpdateArgs.CameraAtAxis.Z) > VDELTA ||
vdelta = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis);
if((vdelta > VDELTA))
return true;
Math.Abs(x.CameraLeftAxis.X - m_thisAgentUpdateArgs.CameraLeftAxis.X) > VDELTA ||
Math.Abs(x.CameraLeftAxis.Y - m_thisAgentUpdateArgs.CameraLeftAxis.Y) > VDELTA ||
// Math.Abs(x.CameraLeftAxis.Z - m_thisAgentUpdateArgs.CameraLeftAxis.Z) > VDELTA ||
vdelta = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis);
if((vdelta > VDELTA))
Math.Abs(x.CameraUpAxis.X - m_thisAgentUpdateArgs.CameraUpAxis.X) > VDELTA ||
Math.Abs(x.CameraUpAxis.Y - m_thisAgentUpdateArgs.CameraUpAxis.Y) > VDELTA
// Math.Abs(x.CameraLeftAxis.Z - m_thisAgentUpdateArgs.CameraLeftAxis.Z) > VDELTA ||
)
return true;
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
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.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>
@ -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);
Exception e = new InventoryArchiverException(errorMessage);
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;
}
@ -420,17 +451,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
{
m_assetGatherer.GatherAll();
m_log.DebugFormat(
"[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count);
int errors = m_assetGatherer.FailedUUIDs.Count;
AssetsRequest ar
= new AssetsRequest(
m_log.DebugFormat(
"[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),
m_assetGatherer.GatheredUuids, m_scene.AssetService,
m_assetGatherer.GatheredUuids, m_assetGatherer.FailedUUIDs.Count,
m_scene.AssetService,
m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
options, ReceivedAllAssets);
WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name));
ar.Execute();
}
else
{

View File

@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// {
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)
{
@ -261,7 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// {
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)
{

View File

@ -412,7 +412,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
Dictionary<UUID, Quaternion> originalRotations = new Dictionary<UUID, Quaternion>();
// 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)
{
@ -423,8 +423,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
objectGroup.RootPart.SetForce(Vector3.Zero);
objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion;
objectGroup.RootPart.KeyframeMotion = null;
// originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion;
// objectGroup.RootPart.KeyframeMotion = null;
Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition;
originalPositions[objectGroup.UUID] = inventoryStoredPosition;
@ -476,7 +476,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
{
objectGroup.AbsolutePosition = originalPositions[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)
objectGroup.RootPart.KeyframeMotion.Resume();
}
@ -989,11 +989,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// one full update during the attachment
// process causes some clients to fail to display the
// attachment properly.
m_Scene.AddNewSceneObject(group, true, false);
if (!attachment)
{
group.AbsolutePosition = pos + veclist[i];
m_Scene.AddNewSceneObject(group, true, false);
// Fire on_rez
group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
@ -1001,6 +1001,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
group.ScheduleGroupForFullUpdate();
}
else
m_Scene.AddNewSceneObject(group, true, false);
// m_log.DebugFormat(
// "[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(
GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
}
}
updater.newTextureID = newTextureID;
}
if (updater.UpdateTimer == 0)
{
lock (Updaters)
{
if (!Updaters.ContainsKey(updater.UpdaterID))
{
if (Updaters.ContainsKey(updater.UpdaterID))
Updaters.Remove(updater.UpdaterID);
}
}
}
}
/// <summary>
/// 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,
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,
string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
string extraParams, bool SetBlending, byte AlphaValue)
{
return AddDynamicTextureURL(simID, primID, contentType, url,
extraParams, updateTimer, SetBlending,
(int)(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, SetBlending,
(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
}
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)
{
if (RenderPlugins.ContainsKey(contentType))
@ -196,7 +191,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.PrimID = primID;
updater.ContentType = contentType;
updater.Url = url;
updater.UpdateTimer = updateTimer;
updater.UpdaterID = UUID.Random();
updater.Params = extraParams;
updater.BlendWithOldTexture = SetBlending;
@ -213,26 +207,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
return updater.UpdaterID;
return updater.newTextureID;
}
return UUID.Zero;
}
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,
string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
string extraParams, bool SetBlending, byte AlphaValue)
{
return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, SetBlending,
(int) (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
return AddDynamicTextureData(simID, primID, contentType, data, extraParams, SetBlending,
(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
}
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))
return UUID.Zero;
@ -258,7 +253,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.PrimID = primID;
updater.ContentType = contentType;
updater.BodyData = data;
updater.UpdateTimer = updateTimer;
updater.UpdaterID = UUID.Random();
updater.Params = extraParams;
updater.BlendWithOldTexture = SetBlending;
@ -314,7 +308,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.UpdatePart(part, (UUID)objReusableTextureUUID);
}
return updater.UpdaterID;
return updater.newTextureID;
}
private string GenerateReusableTextureKey(string data, string extraParams)
@ -404,17 +398,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public byte FrontAlpha = 255;
public string Params;
public UUID PrimID;
public bool SetNewFrontAlpha = false;
public UUID SimUUID;
public UUID UpdaterID;
public int UpdateTimer;
public int Face;
public int Disp;
public string Url;
public UUID newTextureID;
public DynamicTextureUpdater()
{
UpdateTimer = 0;
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.
oldID = tmptex.DefaultTexture.TextureID;
// not using parts number of faces because that fails on old meshs
if (Face == ALL_SIDES)
{
oldID = tmptex.DefaultTexture.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
{
try
{
Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
oldID = texface.TextureID;
texface.TextureID = textureID;
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());
}
@ -491,13 +486,26 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (BlendWithOldTexture)
{
Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture;
if (defaultFace != null)
Primitive.TextureEntryFace curFace;
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)
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;
}
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, byte newAlpha)
{
ManagedImage managedImage;
Image image;
@ -568,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
Bitmap image2 = new Bitmap(image);
image.Dispose();
if (setNewAlpha)
if (newAlpha < 255)
SetAlpha(ref image1, newAlpha);
using(Bitmap joint = MergeBitMaps(image1, image2))

View File

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

View File

@ -77,8 +77,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"",
0);
"");
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,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -108,8 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
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,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -139,8 +135,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
dtText,
"alpha:250",
0);
"alpha:250");
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,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -171,8 +165,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
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,
m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"",
0);
"");
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,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -223,8 +214,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
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,
m_vrm.GetContentType(),
dtText,
"1024",
0);
"1024");
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -263,8 +252,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
dtText,
"1024",
0);
"1024");
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,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -294,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
dtText,
"alpha:250",
0);
"alpha:250");
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,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@ -326,8 +311,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
"");
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)
{
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))
{
graph.FillRectangle(bgFillBrush, 0, 0, width, height);
}
}
for (int w = 0; w < bitmap.Width; w++)
else
{
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++)
{
bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
}
graph.FillRectangle(bgFillBrush, 0, 0, width, height);
}
}
@ -519,8 +511,32 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
// 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
if (nextLine.StartsWith("MoveTo"))
else if (nextLine.StartsWith("MoveTo"))
{
float x = 0;
float y = 0;
@ -625,6 +641,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
startPoint.X += endPoint.X;
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"))
{
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)
{
line = line.Remove(0, startLength);

View File

@ -658,7 +658,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
public void Process()
{
_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
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)
{
string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
ArchiveOneRegion(scene, regionDir, assetUuids);
ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs);
});
// Archive the assets
@ -194,22 +196,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
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,
failedIDs.Count,
m_rootScene.AssetService, m_rootScene.UserAccountService,
m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request");
// CloseArchive() will be called from ReceivedAllAssets()
m_rootScene.RegionInfo.ScopeID, options, null);
ar.Execute();
assetUuids = null;
}
else
{
m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
CloseArchive(string.Empty);
// CloseArchive(string.Empty);
}
CloseArchive(string.Empty);
}
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);
@ -237,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
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))
{
@ -254,17 +255,39 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (SaveAssets)
{
UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids);
UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids, failedIDs, uncertainAssetsUUIDs);
int prevAssets = assetUuids.Count;
foreach (SceneObjectGroup sceneObject in sceneObjects)
{
int curErrorCntr = assetGatherer.ErrorCount;
int possible = assetGatherer.possibleNotAssetCount;
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();
int errors = assetGatherer.FailedUUIDs.Count;
m_log.DebugFormat(
"[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
sceneObjects.Count, assetUuids.Count - prevAssets);
"[ARCHIVER]: {0} region scene objects to save reference {1} possible assets",
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)
@ -572,7 +595,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
foreach (SceneObjectGroup sceneObject in sceneObjects)
{
//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 objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
m_archiveWriter.WriteFile(objectPath, serializedObject);

View File

@ -46,7 +46,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// <value>
/// Post a message to the log every x assets as a progress bar
/// </value>
protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 50;
protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 100;
/// <value>
/// 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
};
/// <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>
/// uuids to request
/// </value>
protected IDictionary<UUID, sbyte> m_uuids;
private int m_previousErrorsCount;
/// <value>
/// Callback used when all the assets requested have been received.
@ -104,6 +87,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// </value>
private int m_repliesRequired;
private System.Timers.Timer m_timeOutTimer;
private bool m_timeout;
/// <value>
/// Asset service used to request the assets
/// </value>
@ -117,205 +103,98 @@ namespace OpenSim.Region.CoreModules.World.Archiver
protected internal AssetsRequest(
AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
int previousErrorsCount,
IAssetService assetService, IUserAccountService userService,
UUID scope, Dictionary<string, object> options,
AssetsRequestCallback assetsRequestCallback)
{
m_assetsArchiver = assetsArchiver;
m_uuids = uuids;
m_previousErrorsCount = previousErrorsCount;
m_assetsRequestCallback = assetsRequestCallback;
m_assetService = assetService;
m_userAccountService = userService;
m_scopeID = scope;
m_options = options;
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()
{
m_requestState = RequestState.Running;
m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
Culture.SetCurrentCulture();
// We can stop here if there are no assets to fetch
if (m_repliesRequired == 0)
{
m_requestState = RequestState.Completed;
PerformAssetsRequestCallback(false);
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)
{
// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key);
// 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;
string thiskey = kvp.Key.ToString();
try
{
lock (this)
{
// Take care of the possibilty that this thread started but was paused just outside the lock before
// 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)
m_timeOutTimer.Enabled = true;
AssetBase asset = m_assetService.Get(thiskey);
if(m_timeout)
break;
m_timeOutTimer.Enabled = false;
if(asset == null)
{
m_notFoundAssetUuids.Add(new UUID(thiskey));
continue;
}
if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT)
m_log.ErrorFormat(
"[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)
sbyte assetType = kvp.Value;
if (asset != null && assetType == (sbyte)AssetType.Unknown)
{
m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace);
}
finally
{
if (timedOut)
WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback");
}
m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType));
asset.Type = assetType;
}
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_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)
{
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>
/// Perform the callback on the original requester of the assets
/// </summary>
protected void PerformAssetsRequestCallback(object o)
private void PerformAssetsRequestCallback(object o)
{
if(m_assetsRequestCallback == null)
return;
Culture.SetCurrentCulture();
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"))
{

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)
{
if (m_landManagementModule != null)

View File

@ -44,14 +44,13 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name='isReuseable'></param>
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,
int updateTimer);
bool SetBlending, byte AlphaValue);
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,
int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face);
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer);
bool SetBlending, int disp, byte AlphaValue, int face);
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams);
/// Apply a dynamically generated texture to all sides of the given prim. The texture is not persisted to the
/// 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>
/// <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="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">
/// If true, the newly generated texture is blended with the appropriate existing ones on the prim
/// </param>
@ -76,7 +73,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
/// </returns>
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer, bool SetBlending, byte AlphaValue);
bool SetBlending, byte AlphaValue);
/// <summary>
/// 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>
/// <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="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">
/// If true, the newly generated texture is blended with the appropriate existing ones on the prim
/// </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
/// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
/// </returns>
UUID AddDynamicTextureData(
UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face);
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
bool SetBlending, int disp, byte AlphaValue, int face);
void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
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)
{
if (part.CollisionSoundType < 0)
return;
if (collidersinfolist.Count == 0 || part == null)
return;
if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
return;
if (part.ParentGroup == null)
SceneObjectGroup sog = part.ParentGroup;
if (sog == null || sog.IsDeleted || sog.inTransit)
return;
if (part.CollisionSoundType < 0)
if(sog.CollisionSoundThrottled(part.CollisionSoundType))
return;
float volume = part.CollisionSoundVolume;
@ -189,15 +193,23 @@ namespace OpenSim.Region.Framework.Scenes
continue;
}
SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id);
SceneObjectPart otherPart = sog.Scene.GetSceneObjectPart(id);
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;
if (!HaveSound)
{
if (otherPart.CollisionSoundType == 1)
if(othersog.CollisionSoundThrottled(otherType))
continue;
if (otherType == 1)
{
soundID = otherPart.CollisionSound;
volume = otherPart.CollisionSoundVolume;
@ -206,7 +218,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
if (otherPart.CollisionSoundType == 2)
if (otherType == 2)
{
volume = otherPart.CollisionSoundVolume;
if (volume == 0.0f)

View File

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

View File

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

View File

@ -425,25 +425,25 @@ namespace OpenSim.Region.Framework.Scenes
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)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
writer.WriteEndElement();
}
private void XWQuat(string name, Quaternion quat)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
writer.WriteEndElement();
}

View File

@ -1651,10 +1651,11 @@ namespace OpenSim.Region.Framework.Scenes
physicsMS2 = (float)(tmpMS2 - tmpMS);
tmpMS = tmpMS2;
/*
// Apply any pending avatar force input to the avatar's velocity
if (Frame % m_update_entitymovement == 0)
m_sceneGraph.UpdateScenePresenceMovement();
*/
if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations)
{
m_sendingCoarseLocations = true;
@ -1942,7 +1943,6 @@ namespace OpenSim.Region.Framework.Scenes
{
if (!m_backingup)
{
m_backingup = true;
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)
{
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);
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)
{
UUID transaction = UUID.Random();
GridInstantMessage msg = new GridInstantMessage();
msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server
msg.toAgentID = new Guid(ret.Key.ToString());
msg.imSessionID = new Guid(transaction.ToString());
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
msg.fromAgentID = Guid.Empty; // From server
msg.toAgentID = ret.Key.Guid;
msg.imSessionID = Guid.NewGuid();
msg.timestamp = unixtime;
msg.fromAgentName = "Server";
msg.dialog = (byte)19; // Object msg
msg.dialog = 19; // Object msg
msg.fromGroup = false;
msg.offline = (byte)1;
msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
msg.offline = 1;
msg.ParentEstateID = estateid;
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.
msg.binaryBucket = Util.StringToBytes256("\0");
msg.binaryBucket = new Byte[1] {0};
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);
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);
IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
if (tr != null)
tr.SendInstantMessage(msg, delegate(bool success) { });
}
m_returns.Clear();
}
finally
{
m_backingup = false;
}
}
}
/// <summary>
/// Synchronous force backup. For deletes and links/unlinks
@ -4805,16 +4825,34 @@ Label_GroupsDone:
public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position,
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
remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found.");
return;
}
RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags);
EntityTransferModule.Teleport(sp, regionHandle, position, lookat, teleportFlags);
}
/// <summary>
@ -4828,19 +4866,17 @@ Label_GroupsDone:
public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position,
Vector3 lookAt, uint teleportFlags)
{
ScenePresence sp = GetScenePresence(remoteClient.AgentId);
if (sp != null)
{
if (EntityTransferModule != null)
{
EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
}
else
if (EntityTransferModule == null)
{
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)

View File

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

View File

@ -1259,6 +1259,8 @@ namespace OpenSim.Region.Framework.Scenes
set { m_LoopSoundSlavePrims = value; }
}
private double m_lastCollisionSoundMS;
/// <summary>
/// The UUID for the region this object is in.
/// </summary>
@ -1336,7 +1338,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public SceneObjectGroup()
{
m_lastCollisionSoundMS = Util.GetTimeStampMS() + 1000.0;
}
/// <summary>
@ -2716,35 +2718,22 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.KeyframeMotion.Stop();
RootPart.KeyframeMotion = null;
}
UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
UpdateFlags(usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
}
public void ScriptSetTemporaryStatus(bool makeTemporary)
{
UpdatePrimFlags(RootPart.LocalId, UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect);
UpdateFlags(UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect);
}
public void ScriptSetPhantomStatus(bool makePhantom)
{
UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect);
UpdateFlags(UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect);
}
public void ScriptSetVolumeDetect(bool makeVolumeDetect)
{
UpdatePrimFlags(RootPart.LocalId, 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();
*/
UpdateFlags(UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect);
}
public void applyImpulse(Vector3 impulse)
@ -4029,14 +4018,13 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="SetTemporary"></param>
/// <param name="SetPhantom"></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;
SceneObjectPart selectionPart = GetPart(localID);
if (Scene != null)
{
if (SetTemporary)
{
DetachFromBackup();
@ -4051,14 +4039,10 @@ namespace OpenSim.Region.Framework.Scenes
AttachToBackup();
}
m_scene.EventManager.TriggerParcelPrimCountTainted();
}
if (selectionPart != null)
{
SceneObjectPart[] parts = m_parts.GetArray();
if (Scene != null && UsePhysics)
if (UsePhysics)
{
int maxprims = m_scene.m_linksetPhysCapacity;
bool checkShape = (maxprims > 0 &&
@ -4106,7 +4090,8 @@ namespace OpenSim.Region.Framework.Scenes
}
else
m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
}
m_scene.EventManager.TriggerParcelPrimCountTainted();
}
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
}
}

View File

@ -329,7 +329,8 @@ namespace OpenSim.Region.Framework.Scenes
private byte[] m_TextureAnimation;
private byte m_clickAction;
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_scriptAccessPin;
@ -369,9 +370,9 @@ namespace OpenSim.Region.Framework.Scenes
protected Vector3 m_lastPosition;
protected Quaternion m_lastRotation;
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 int m_lastUpdateSentTime;
protected double m_lastUpdateSentTime;
protected float m_buoyancy = 0.0f;
protected Vector3 m_force;
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.
PhysicsActor actor = PhysActor;
if (ParentID == 0)
if (_parentID == 0)
{
if (actor != null)
m_groupPosition = actor.Position;
@ -838,7 +839,7 @@ namespace OpenSim.Region.Framework.Scenes
try
{
// Root prim actually goes at Position
if (ParentID == 0)
if (_parentID == 0)
{
actor.Position = value;
}
@ -880,7 +881,7 @@ namespace OpenSim.Region.Framework.Scenes
ParentGroup.InvalidBoundsRadius();
PhysicsActor actor = PhysActor;
if (ParentID != 0 && actor != null)
if (_parentID != 0 && actor != null)
{
actor.Position = GetWorldPosition();
actor.Orientation = GetWorldRotation();
@ -940,7 +941,7 @@ namespace OpenSim.Region.Framework.Scenes
PhysicsActor actor = PhysActor;
// 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 (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;
return m_rotationOffset;
@ -957,7 +958,7 @@ namespace OpenSim.Region.Framework.Scenes
try
{
// Root prim gets value directly
if (ParentID == 0)
if (_parentID == 0)
{
actor.Orientation = value;
//m_log.Info("[PART]: RO1:" + actor.Orientation.ToString());
@ -1103,8 +1104,8 @@ namespace OpenSim.Region.Framework.Scenes
{
get
{
if (m_text.Length > 255)
return m_text.Substring(0, 254);
if (m_text.Length > 256) // yes > 254
return m_text.Substring(0, 256);
return m_text;
}
set { m_text = value; }
@ -1258,6 +1259,9 @@ namespace OpenSim.Region.Framework.Scenes
{
get
{
if (_parentID == 0)
return GroupPosition;
return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
}
}
@ -1379,7 +1383,8 @@ namespace OpenSim.Region.Framework.Scenes
public UUID LastOwnerID
{
get { return _lastOwnerID; }
set { _lastOwnerID = value; }
set {
_lastOwnerID = value; }
}
public UUID RezzerID
@ -2422,7 +2427,7 @@ namespace OpenSim.Region.Framework.Scenes
PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
if (ParentID != 0 && ParentID != LocalId)
if (_parentID != 0 && _parentID != LocalId)
{
PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
@ -2788,12 +2793,13 @@ namespace OpenSim.Region.Framework.Scenes
{
ColliderArgs colliderArgs = new ColliderArgs();
List<DetectedObject> colliding = new List<DetectedObject>();
Scene parentScene = ParentGroup.Scene;
foreach (uint localId in colliders)
{
if (localId == 0)
continue;
SceneObjectPart obj = ParentGroup.Scene.GetSceneObjectPart(localId);
SceneObjectPart obj = parentScene.GetSceneObjectPart(localId);
if (obj != null)
{
if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
@ -2801,7 +2807,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
ScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
ScenePresence av = parentScene.GetScenePresence(localId);
if (av != null && (!av.IsChildAgent))
{
if (!dest.CollisionFilteredOut(av.UUID, av.Name))
@ -2874,10 +2880,13 @@ namespace OpenSim.Region.Framework.Scenes
public void PhysicsCollision(EventArgs e)
{
if (ParentGroup.Scene == null || ParentGroup.IsDeleted)
if (ParentGroup.Scene == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
return;
// this a thread from physics ( heartbeat )
bool thisHitLand = false;
bool startLand = false;
bool endedLand = false;
CollisionEventUpdate a = (CollisionEventUpdate)e;
Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList;
@ -2887,13 +2896,17 @@ namespace OpenSim.Region.Framework.Scenes
if (collissionswith.Count == 0)
{
if (m_lastColliders.Count == 0)
if (m_lastColliders.Count == 0 && !m_lastLandCollide)
return; // nothing to do
endedLand = m_lastLandCollide;
m_lastLandCollide = false;
foreach (uint localID in m_lastColliders)
{
endedColliders.Add(localID);
}
m_lastColliders.Clear();
}
else
@ -2908,6 +2921,25 @@ namespace OpenSim.Region.Framework.Scenes
ContactPoint curcontact;
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);
if (!m_lastColliders.Contains(id))
@ -2926,15 +2958,25 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
}
else
{
foreach (uint id in collissionswith.Keys)
{
if(id == 0)
{
thisHitLand = true;
if (!m_lastLandCollide)
startLand = true;
}
else
{
thisHitColliders.Add(id);
if (!m_lastColliders.Contains(id))
startedColliders.Add(id);
}
}
}
// calculate things that ended colliding
foreach (uint localID in m_lastColliders)
@ -2951,22 +2993,32 @@ namespace OpenSim.Region.Framework.Scenes
foreach (uint localID in endedColliders)
m_lastColliders.Remove(localID);
if(m_lastLandCollide && !thisHitLand)
endedLand = true;
m_lastLandCollide = thisHitLand;
// play sounds.
if (soundinfolist.Count > 0)
CollisionSounds.PartCollisionSound(this, soundinfolist);
}
SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
if (!VolumeDetectActive)
SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
EventManager eventmanager = ParentGroup.Scene.EventManager;
if (startedColliders.Contains(0))
SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
if (m_lastColliders.Contains(0))
SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
if (endedColliders.Contains(0))
SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
SendCollisionEvent(scriptEvents.collision_start, startedColliders, eventmanager.TriggerScriptCollidingStart);
if (!VolumeDetectActive)
SendCollisionEvent(scriptEvents.collision , m_lastColliders , eventmanager.TriggerScriptColliding);
SendCollisionEvent(scriptEvents.collision_end , endedColliders , eventmanager.TriggerScriptCollidingEnd);
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
@ -2985,7 +3037,7 @@ namespace OpenSim.Region.Framework.Scenes
volume = 0;
int now = Util.EnvironmentTickCount();
if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
if(Util.EnvironmentTickCountSubtract(now, LastColSoundSentTime) < 200)
return;
LastColSoundSentTime = now;
@ -3026,7 +3078,7 @@ namespace OpenSim.Region.Framework.Scenes
//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.
// This happens when linksets are modified to use flexible links rather than
@ -3236,7 +3288,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary>
/// 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>
public void ScheduleTerseUpdate()
{
@ -3295,21 +3347,6 @@ namespace OpenSim.Region.Framework.Scenes
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
{
SendFullUpdateToClient(remoteClient);
@ -3325,12 +3362,12 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
return;
// Update the "last" values
m_lastPosition = OffsetPosition;
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount;
m_lastUpdateSentTime = Util.GetTimeStampMS();
ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
@ -3344,12 +3381,12 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
return;
// Update the "last" values
m_lastPosition = OffsetPosition;
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount;
m_lastUpdateSentTime = Util.GetTimeStampMS();
if (ParentGroup.IsAttachment)
{
@ -3395,42 +3432,131 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
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>
/// Tell all the prims which have had updates scheduled
/// </summary>
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)
{
case UpdateRequired.TERSE:
{
case UpdateRequired.NONE:
ClearUpdateSchedule();
// Throw away duplicate or insignificant updates
if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
!Acceleration.Equals(m_lastAcceleration) ||
!Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
!AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
!OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
break;
case UpdateRequired.TERSE:
ClearUpdateSchedule();
bool needupdate = true;
double now = Util.GetTimeStampMS();
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;
}
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();
SendFullUpdateToAllClientsInternal();
break;
}
}
}
/// <summary>
@ -3441,13 +3567,15 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
if (ParentGroup == null || ParentGroup.Scene == null)
return;
ClearUpdateSchedule();
// Update the "last" values
m_lastPosition = OffsetPosition;
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount;
m_lastUpdateSentTime = Util.GetTimeStampMS();
ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
{
@ -3460,13 +3588,15 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
if (ParentGroup == null || ParentGroup.Scene == null)
return;
ClearUpdateSchedule();
// Update the "last" values
m_lastPosition = OffsetPosition;
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Environment.TickCount;
m_lastUpdateSentTime = Util.GetTimeStampMS();
if (ParentGroup.IsAttachment)
{
@ -4783,7 +4913,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter
pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
pa.OnOutOfBounds += PhysicsOutOfBounds;
if (ParentID != 0 && ParentID != LocalId)
if (_parentID != 0 && _parentID != LocalId)
{
PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;

View File

@ -279,8 +279,11 @@ namespace OpenSim.Region.Framework.Scenes
private bool MouseDown = false;
public Vector3 lastKnownAllowedPosition;
public bool sentMessageAboutRestrictedParcelFlyingDown;
public Vector4 CollisionPlane = Vector4.UnitW;
public Vector4 m_lastCollisionPlane = Vector4.UnitW;
private byte m_lastState;
private Vector3 m_lastPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
@ -2818,16 +2821,13 @@ namespace OpenSim.Region.Framework.Scenes
CameraAtAxis = agentData.CameraAtAxis;
CameraLeftAxis = agentData.CameraLeftAxis;
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;
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.
// 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
// 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)
{
// this does need to be more complex later
Vector3 vel = Velocity;
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.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.Z - m_lastRotation.Z) > ROTATION_TOLERANCE ||
(vel == Vector3.Zero && m_lastVelocity != Vector3.Zero) ||
Math.Abs(dpos.X) > POSITION_LARGETOLERANCE ||
Math.Abs(dpos.Y) > 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.Z) > POSITION_SMALLTOLERANCE)
&& 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();
// }
}
}
CheckForSignificantMovement();
}
@ -3921,11 +3917,14 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void SendTerseUpdateToAllClients()
{
m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
// Update the "last" values
m_lastState = State;
m_lastPosition = m_pos;
m_lastRotation = m_bodyRot;
m_lastVelocity = Velocity;
m_lastCollisionPlane = CollisionPlane;
m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
// Update the "last" values
TriggerScenePresenceUpdated();
}

View File

@ -86,9 +86,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteStartElement("CoalescedObject");
writer.WriteAttributeString("x", size.X.ToString());
writer.WriteAttributeString("y", size.Y.ToString());
writer.WriteAttributeString("z", size.Z.ToString());
writer.WriteAttributeString("x", size.X.ToString(Culture.FormatProvider));
writer.WriteAttributeString("y", size.Y.ToString(Culture.FormatProvider));
writer.WriteAttributeString("z", size.Z.ToString(Culture.FormatProvider));
// Embed the offsets into the group XML
for (int i = 0; i < coaObjects.Count; i++)
@ -100,9 +100,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
// i, obj.Name);
writer.WriteStartElement("SceneObjectGroup");
writer.WriteAttributeString("offsetx", offsets[i].X.ToString());
writer.WriteAttributeString("offsety", offsets[i].Y.ToString());
writer.WriteAttributeString("offsetz", offsets[i].Z.ToString());
writer.WriteAttributeString("offsetx", offsets[i].X.ToString(Culture.FormatProvider));
writer.WriteAttributeString("offsety", offsets[i].Y.ToString(Culture.FormatProvider));
writer.WriteAttributeString("offsetz", offsets[i].Z.ToString(Culture.FormatProvider));
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 }))
{
try {
try
{
return FromOriginalXmlFormat(reader);
}
catch (Exception e)
@ -109,11 +110,23 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
}
}
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
// ever a problem.
sceneObject.LoadScriptState(reader);
sceneObject.InvalidateDeepEffectivePerms();
return sceneObject;
}
@ -210,9 +223,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
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)
sceneObject.SaveScriptedState(writer);
if (!noRootElement)
writer.WriteEndElement(); // SceneObjectGroup
@ -1459,10 +1482,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("Description", sop.Description);
writer.WriteStartElement("Color");
writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture));
writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture));
writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture));
writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture));
writer.WriteElementString("R", sop.Color.R.ToString(Culture.FormatProvider));
writer.WriteElementString("G", sop.Color.G.ToString(Culture.FormatProvider));
writer.WriteElementString("B", sop.Color.B.ToString(Culture.FormatProvider));
writer.WriteElementString("A", sop.Color.A.ToString(Culture.FormatProvider));
writer.WriteEndElement();
writer.WriteElementString("Text", sop.Text);
@ -1505,7 +1528,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("NextOwnerMask", sop.NextOwnerMask.ToString());
WriteFlags(writer, "Flags", sop.Flags.ToString(), 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)
writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
WriteVector(writer, "AttachedPos", sop.AttachedPos);
@ -1525,7 +1548,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("PayPrice3", sop.PayPrice[3].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, "Torque", sop.Torque);
@ -1542,22 +1565,22 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("RotationAxisLocks", sop.RotationAxisLocks.ToString().ToLower());
writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
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)
writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
writer.WriteElementString("Friction", sop.Friction.ToString(Culture.FormatProvider));
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)
writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString(Culture.FormatProvider));
WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
// if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
{
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("SoundRadius", sop.SoundRadius.ToString().ToLower());
writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString(Culture.FormatProvider));
}
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)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
writer.WriteEndElement();
}
static void WriteQuaternion(XmlTextWriter writer, string name, Quaternion quat)
{
writer.WriteStartElement(name);
writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
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'.
writer.WriteElementString("FlexiSoftness", shp.FlexiSoftness.ToString());
writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString());
writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString());
writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString());
writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString());
writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString());
writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString());
writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString());
writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorR", shp.LightColorR.ToString());
writer.WriteElementString("LightColorG", shp.LightColorG.ToString());
writer.WriteElementString("LightColorB", shp.LightColorB.ToString());
writer.WriteElementString("LightColorA", shp.LightColorA.ToString());
writer.WriteElementString("LightRadius", shp.LightRadius.ToString());
writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString());
writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString());
writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString());
writer.WriteElementString("LightColorR", shp.LightColorR.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorG", shp.LightColorG.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorB", shp.LightColorB.ToString(Culture.FormatProvider));
writer.WriteElementString("LightColorA", shp.LightColorA.ToString(Culture.FormatProvider));
writer.WriteElementString("LightRadius", shp.LightRadius.ToString(Culture.FormatProvider));
writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString(Culture.FormatProvider));
writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString(Culture.FormatProvider));
writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString(Culture.FormatProvider));
writer.WriteElementString("FlexiEntry", shp.FlexiEntry.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);
SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10);
so1.ScriptSetPhysicsStatus(true);
m_scene.AddSceneObject(so1);
so1.ScriptSetPhysicsStatus(true);
Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3));
Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3));

View File

@ -65,7 +65,10 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
/// <value>The gathered uuids.</value>
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>
/// Gets the next UUID to inspect.
/// </summary>
@ -92,7 +95,10 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="assetService">
/// Asset service.
/// </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>
/// 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.
/// </param>
/// <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.
/// </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;
GatheredUuids = collector;
// FIXME: Not efficient for searching, can improve.
m_assetUuidsToInspect = new Queue<UUID>();
FailedUUIDs = failedIDs;
UncertainAssetsUUIDs = uncertainAssetsUUIDs;
ErrorCount = 0;
possibleNotAssetCount = 0;
}
/// <summary>
@ -120,6 +130,19 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="uuid">UUID.</param>
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))
return false;
@ -141,7 +164,9 @@ namespace OpenSim.Region.Framework.Scenes
public void AddForInspection(SceneObjectGroup sceneObject)
{
// 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;
for (int i = 0; i < parts.Length; i++)
@ -149,7 +174,7 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart part = parts[i];
// 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
{
@ -207,8 +232,6 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat(
// "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}",
// tii.Name, tii.Type, part.Name, part.UUID);
if (!GatheredUuids.ContainsKey(tii.AssetID))
AddForInspection(tii.AssetID, (sbyte)tii.Type);
}
@ -225,9 +248,6 @@ namespace OpenSim.Region.Framework.Scenes
catch (Exception 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>
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
if (GatheredUuids.ContainsKey(assetUuid))
return;
AssetBase assetBase;
try
{
AssetBase assetBase = GetAsset(assetUuid);
if (null != assetBase)
assetBase = GetAsset(assetUuid);
}
catch (Exception e)
{
sbyte assetType = assetBase.Type;
GatheredUuids[assetUuid] = assetType;
m_log.ErrorFormat("[UUID GATHERER]: Failed to get asset {0} : {1}", assetUuid, e.Message);
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)
{
RecordWearableAssetUuids(assetBase);
@ -316,17 +379,31 @@ namespace OpenSim.Region.Framework.Scenes
RecordSceneObjectAssetUuids(assetBase);
}
}
}
catch (Exception)
catch (Exception e)
{
m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset id {0}", assetUuid);
throw;
m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset with id {0} type {1}: {2}", assetUuid, assetType, e.Message);
GatheredUuids.Remove(assetUuid);
ErrorCount++;
FailedUUIDs.Add(assetUuid);
}
}
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
if(FailedUUIDs.Contains(assetUuid))
{
if(UncertainAssetsUUIDs.Contains(assetUuid))
possibleNotAssetCount++;
else
ErrorCount++;
return;
}
if(GatheredUuids.ContainsKey(assetUuid))
return;
try
{
if ((sbyte)AssetType.Bodypart == assetType
@ -458,8 +535,11 @@ namespace OpenSim.Region.Framework.Scenes
foreach (Match uuidMatch in uuidMatches)
{
UUID uuid = new UUID(uuidMatch.Value);
if(uuid == UUID.Zero)
continue;
// m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid);
if(!UncertainAssetsUUIDs.Contains(uuid))
UncertainAssetsUUIDs.Add(uuid);
AddForInspection(uuid);
}
}

View File

@ -59,23 +59,23 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// </summary>
/// <remarks>
/// Config Settings Documentation.
/// Each configuration setting can be specified in two places: OpenSim.ini 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.
/// Configuration setting can be specified in two places: OpenSim.ini and/or Regions.ini.
///
/// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis.
/// All other settings under [AutoBackupModule] are ignored if AutoBackupModuleEnabled is false, even per-region settings!
/// AutoBackup: True/False. Default: False. If True, activate auto backup functionality.
/// 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.
/// OpenSim.ini only settings section [AutoBackupModule]
/// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module.
/// if false module is disable and all rest is ignored
/// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours).
/// The number of minutes between each backup attempt.
/// If a negative or zero value is given, it is equivalent to setting AutoBackup = False.
/// AutoBackupBusyCheck: True/False. Default: True.
/// If True, we will only take an auto-backup if a set of conditions are met.
/// These conditions are heuristics to try and avoid taking a backup when the sim is busy.
/// AutoBackupDir: String. Default: "." (the current directory).
/// A directory (absolute or relative) where backups should be saved.
/// AutoBackupKeepFilesForDays remove files older than this number of days. 0 disables
///
/// 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
/// 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
@ -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.
/// "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.
/// 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>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AutoBackupModule")]
public class AutoBackupModule : ISharedRegionModule
{
private static readonly ILog m_log =
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 Dictionary<IScene, AutoBackupModuleState> m_states =
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 bool m_enabled;
private ICommandConsole m_console;
private List<Scene> m_Scenes = new List<Scene> ();
/// <summary>
/// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
/// </summary>
private bool m_closed;
private Timer m_masterTimer;
private bool m_busy;
private int m_KeepFilesForDays = -1;
private string m_backupDir;
private bool m_doneFirst;
private double m_baseInterval;
private IConfigSource m_configSource;
@ -159,36 +147,38 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
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
this.m_configSource = source;
m_configSource = source;
IConfig moduleConfig = source.Configs["AutoBackupModule"];
if (moduleConfig == null)
{
this.m_enabled = false;
m_enabled = false;
return;
}
else
{
this.m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false);
if (this.m_enabled)
{
m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false);
if(!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");
}
else
{
return;
}
}
m_masterTimer = new Timer();
m_masterTimer.Interval = m_baseInterval;
m_masterTimer.Elapsed += HandleElapsed;
m_masterTimer.AutoReset = false;
Timer defTimer = new Timer(43200000);
this.m_defaultState.Timer = defTimer;
this.m_timers.Add(43200000, defTimer);
defTimer.Elapsed += this.HandleElapsed;
defTimer.AutoReset = true;
defTimer.Start();
m_console = MainConsole.Instance;
AutoBackupModuleState abms = this.ParseConfig(null, true);
m_log.Debug("[AUTO BACKUP]: Here is the default config:");
m_log.Debug(abms.ToString());
m_console.Commands.AddCommand (
"AutoBackup", true, "dooarbackup",
"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>
@ -196,13 +186,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// </summary>
void IRegionModuleBase.Close()
{
if (!this.m_enabled)
{
if (!m_enabled)
return;
}
// We don't want any timers firing while the sim's coming down; strange things may happen.
this.StopAllTimers();
m_masterTimer.Dispose();
}
/// <summary>
@ -211,18 +199,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="scene"></param>
void IRegionModuleBase.AddRegion (Scene scene)
{
if (!this.m_enabled) {
if (!m_enabled)
return;
}
lock (m_Scenes) {
m_Scenes.Add (scene);
}
m_console = MainConsole.Instance;
m_console.Commands.AddCommand (
"AutoBackup", false, "dobackup",
"dobackup",
"do backup.", DoBackup);
lock (m_Scenes)
m_Scenes.Add (scene);
}
/// <summary>
@ -231,28 +212,14 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="scene">The scene (region) to stop performing AutoBackup on.</param>
void IRegionModuleBase.RemoveRegion(Scene scene)
{
if (!this.m_enabled)
{
if (m_enabled)
return;
}
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)
lock(m_Scenes)
{
this.m_timerMap.Remove(timer);
this.m_timers.Remove(timer.Interval);
timer.Close();
}
this.m_states.Remove(scene);
if (m_states.ContainsKey(scene))
m_states.Remove(scene);
m_Scenes.Remove(scene);
}
}
@ -263,22 +230,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <param name="scene">The scene to (possibly) perform AutoBackup on.</param>
void IRegionModuleBase.RegionLoaded(Scene scene)
{
if (!this.m_enabled)
{
if (!m_enabled)
return;
}
// This really ought not to happen, but just in case, let's pretend it didn't...
if (scene == null)
{
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_busy = false;
m_masterTimer.Start();
}
/// <summary>
@ -292,24 +266,122 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
private void DoBackup (string module, string[] args)
{
if (args.Length != 2) {
MainConsole.Instance.OutputFormat ("Usage: dobackup <regionname>");
if (!m_enabled)
return;
if (args.Length != 2)
{
MainConsole.Instance.OutputFormat ("Usage: dooarbackup <regionname>");
return;
}
if(m_busy)
{
MainConsole.Instance.OutputFormat ("Already doing a backup, please try later");
return;
}
m_masterTimer.Stop();
m_busy = true;
bool found = false;
string name = args [1];
lock (m_Scenes) {
foreach (Scene s in m_Scenes) {
string test = s.Name.ToString ();
if (test == name) {
Scene[] scenes;
lock (m_Scenes)
scenes = m_Scenes.ToArray();
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;
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);
}
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>
@ -319,329 +391,49 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
/// <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>
/// <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;
string sRegionLabel;
// string prepend;
AutoBackupModuleState state;
if(scene == null)
return null;
string sRegionName;
AutoBackupModuleState state = null;
if (parseDefault)
{
sRegionName = null;
sRegionLabel = "DEFAULT";
// prepend = "";
state = this.m_defaultState;
}
else
{
sRegionName = scene.RegionInfo.RegionName;
sRegionLabel = sRegionName;
// prepend = sRegionName + ".";
state = null;
}
// Read the config settings and set variables.
IConfig regionConfig = (scene != null ? scene.Config.Configs[sRegionName] : null);
IConfig config = this.m_configSource.Configs["AutoBackupModule"];
if (config == null)
{
// defaultState would be disabled too if the section doesn't exist.
state = this.m_defaultState;
return state;
}
IConfig regionConfig = scene.Config.Configs[sRegionName];
if (regionConfig == null)
return null;
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();
}
if (state != null)
{
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;
}
state.Enabled = regionConfig.GetBoolean("AutoBackup", m_defaultState.Enabled);
// Included Option To Skip Assets
bool tmpSkipAssets = ResolveBoolean("AutoBackupSkipAssets",
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;
}
state.SkipAssets = regionConfig.GetBoolean("AutoBackupSkipAssets", m_defaultState.SkipAssets);
// Set file naming algorithm
string stmpNamingType = ResolveString("AutoBackupNaming",
this.m_defaultState.NamingType.ToString(), config, regionConfig);
string stmpNamingType = regionConfig.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 region " + sRegionLabel + ": " +
m_log.Warn("Unknown naming type specified for region " + sRegionName + ": " +
stmpNamingType);
tmpNamingType = NamingType.Time;
}
m_defaultState.NamingType = tmpNamingType;
if (state == null && tmpNamingType != this.m_defaultState.NamingType)
{
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;
state.Script = regionConfig.GetString("AutoBackupScript", m_defaultState.Script);
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>
/// 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>
private void HandleElapsed(object sender, ElapsedEventArgs e)
{
// TODO: heuristic thresholds are per-region, so we should probably run heuristics once per region
// 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)
{
if (!m_enabled || m_busy)
return;
}
bool heuristicsRun = false;
bool heuristicsPassed = false;
if (!this.m_timerMap.ContainsKey((Timer) sender))
m_busy = true;
if(m_doneFirst && m_KeepFilesForDays > 0)
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 (tmap != null && tmap.Count > 0)
if (m_enabled)
{
foreach (IScene scene in tmap)
{
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);
m_masterTimer.Start();
m_busy = false;
}
// Remove Old Backups
this.RemoveOldFiles(state);
}
}
m_doneFirst = true;
}
/// <summary>
@ -723,21 +479,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
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>();
if(iram == null)
return;
string savePath = BuildOarPath(scene.RegionInfo.RegionName,
state.BackupDir,
m_backupDir,
state.NamingType);
if (savePath == null)
{
m_log.Warn("[AUTO BACKUP]: savePath is null in HandleElapsed");
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);
// Must pass options, even if dictionary is empty!
@ -747,16 +511,24 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
options["noassets"] = true;
iram.ArchiveRegion(savePath, guid, options);
ExecuteScript(state.Script, savePath);
}
// 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
if (state.KeepFilesForDays > 0)
string[] files;
try
{
string[] files = Directory.GetFiles(state.BackupDir, "*.oar");
DateTime CuttOffDate = DateTime.Now.AddDays(0 - state.KeepFilesForDays);
files = Directory.GetFiles(m_backupDir, "*.oar");
}
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)
{
@ -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...
/// 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;
}
/// <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>
/// 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.
@ -919,18 +616,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
" 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>
/// Determine the next unique filename by number, for "Sequential" AutoBackupNamingType.
/// </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
{
private Dictionary<Guid, string> m_liveRequests = null;
public AutoBackupModuleState()
{
this.Enabled = false;
this.BackupDir = ".";
this.BusyCheck = true;
this.SkipAssets = false;
this.Timer = null;
this.NamingType = NamingType.Time;
this.Script = null;
this.KeepFilesForDays = 0;
Enabled = false;
SkipAssets = false;
NamingType = NamingType.Time;
Script = null;
}
public Dictionary<Guid, string> LiveRequests
public AutoBackupModuleState(AutoBackupModuleState copyFrom)
{
get {
return this.m_liveRequests ??
(this.m_liveRequests = new Dictionary<Guid, string>(1));
}
Enabled = copyFrom.Enabled;
SkipAssets = copyFrom.SkipAssets;
NamingType = copyFrom.NamingType;
Script = copyFrom.Script;
}
public bool Enabled
@ -66,33 +60,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
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
{
get;
@ -105,36 +72,19 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
set;
}
public string BackupDir
{
get;
set;
}
public NamingType NamingType
{
get;
set;
}
public int KeepFilesForDays
{
get;
set;
}
public new string ToString()
{
string retval = "";
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]: Backup Dir: " + BackupDir + "\n";
retval += "[AUTO BACKUP]: Script: " + Script + "\n";
return retval;
}
}
}

View File

@ -27,8 +27,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Timers;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using OpenMetaverse;
using log4net;
using Mono.Addins;
@ -38,9 +43,7 @@ using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using Timer= System.Timers.Timer;
namespace OpenSim.Region.OptionalModules.World.TreePopulator
{
@ -48,7 +51,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
/// Version 2.02 - Still hacky
/// </summary>
[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 readonly Commander m_commander = new Commander("tree");
@ -82,20 +85,20 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
{
Copse cp = (Copse)DeserializeObject(fileName);
this.m_name = cp.m_name;
this.m_frozen = cp.m_frozen;
this.m_tree_quantity = cp.m_tree_quantity;
this.m_treeline_high = cp.m_treeline_high;
this.m_treeline_low = cp.m_treeline_low;
this.m_range = cp.m_range;
this.m_tree_type = cp.m_tree_type;
this.m_seed_point = cp.m_seed_point;
this.m_initial_scale = cp.m_initial_scale;
this.m_maximum_scale = cp.m_maximum_scale;
this.m_initial_scale = cp.m_initial_scale;
this.m_rate = cp.m_rate;
this.m_planted = planted;
this.m_trees = new List<UUID>();
m_name = cp.m_name;
m_frozen = cp.m_frozen;
m_tree_quantity = cp.m_tree_quantity;
m_treeline_high = cp.m_treeline_high;
m_treeline_low = cp.m_treeline_low;
m_range = cp.m_range;
m_tree_type = cp.m_tree_type;
m_seed_point = cp.m_seed_point;
m_initial_scale = cp.m_initial_scale;
m_maximum_scale = cp.m_maximum_scale;
m_initial_scale = cp.m_initial_scale;
m_rate = cp.m_rate;
m_planted = planted;
m_trees = new List<UUID>();
}
public Copse(string copsedef)
@ -103,61 +106,63 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
char[] delimiterChars = {':', ';'};
string[] field = copsedef.Split(delimiterChars);
this.m_name = field[1].Trim();
this.m_frozen = (copsedef[0] == 'F');
this.m_tree_quantity = int.Parse(field[2]);
this.m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo);
this.m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo);
this.m_range = double.Parse(field[5], Culture.NumberFormatInfo);
this.m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]);
this.m_seed_point = Vector3.Parse(field[7]);
this.m_initial_scale = Vector3.Parse(field[8]);
this.m_maximum_scale = Vector3.Parse(field[9]);
this.m_rate = Vector3.Parse(field[10]);
this.m_planted = true;
this.m_trees = new List<UUID>();
m_name = field[1].Trim();
m_frozen = (copsedef[0] == 'F');
m_tree_quantity = int.Parse(field[2]);
m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo);
m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo);
m_range = double.Parse(field[5], Culture.NumberFormatInfo);
m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]);
m_seed_point = Vector3.Parse(field[7]);
m_initial_scale = Vector3.Parse(field[8]);
m_maximum_scale = Vector3.Parse(field[9]);
m_rate = Vector3.Parse(field[10]);
m_planted = true;
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)
{
this.m_name = name;
this.m_frozen = false;
this.m_tree_quantity = quantity;
this.m_treeline_high = high;
this.m_treeline_low = low;
this.m_range = range;
this.m_tree_type = type;
this.m_seed_point = point;
this.m_initial_scale = scale;
this.m_maximum_scale = max_scale;
this.m_rate = rate;
this.m_planted = false;
this.m_trees = trees;
m_name = name;
m_frozen = false;
m_tree_quantity = quantity;
m_treeline_high = high;
m_treeline_low = low;
m_range = range;
m_tree_type = type;
m_seed_point = point;
m_initial_scale = scale;
m_maximum_scale = max_scale;
m_rate = rate;
m_planted = false;
m_trees = trees;
}
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};",
frozen,
this.m_name,
this.m_tree_quantity,
this.m_treeline_high,
this.m_treeline_low,
this.m_range,
this.m_tree_type,
this.m_seed_point.ToString(),
this.m_initial_scale.ToString(),
this.m_maximum_scale.ToString(),
this.m_rate.ToString());
m_name,
m_tree_quantity,
m_treeline_high,
m_treeline_low,
m_range,
m_tree_type,
m_seed_point.ToString(),
m_initial_scale.ToString(),
m_maximum_scale.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 bool m_active_trees = false;
private bool m_enabled = true; // original default
private bool m_allowGrow = true; // original default
Timer CalculateTrees;
@ -174,51 +179,51 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
public void Initialise(IConfigSource config)
{
// ini file settings
try
IConfig moduleConfig = config.Configs["Trees"];
if (moduleConfig != null)
{
m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees);
}
catch (Exception)
{
m_log.Debug("[TREES]: ini failure for active_trees - using default");
m_enabled = moduleConfig.GetBoolean("enabled", m_enabled);
m_active_trees = moduleConfig.GetBoolean("active_trees", m_active_trees);
m_allowGrow = moduleConfig.GetBoolean("allowGrow", m_allowGrow);
m_update_ms = moduleConfig.GetDouble("update_rate", m_update_ms);
}
try
{
m_update_ms = config.Configs["Trees"].GetDouble("update_rate", m_update_ms);
}
catch (Exception)
{
m_log.Debug("[TREES]: ini failure for update_rate - using default");
}
if(!m_enabled)
return;
m_copses = new List<Copse>();
mylock = new object();
InstallCommands();
m_log.Debug("[TREES]: Initialised tree module");
m_log.Debug("[TREES]: Initialised tree populator module");
}
public void AddRegion(Scene scene)
{
if(!m_enabled)
return;
m_scene = scene;
m_scene.RegisterModuleCommander(m_commander);
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
m_scene.EventManager.OnPrimsLoaded += EventManager_OnPrimsLoaded;
}
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)
{
ReloadCopse();
if (m_copse.Count > 0)
m_log.Info("[TREES]: Copse load complete");
if (m_active_trees)
activeizeTreeze(true);
}
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
private void HandleTreeActive(Object[] args)
@ -267,27 +282,59 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
string copsename = ((string)args[0]).Trim();
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;
List<UUID> losttrees = new List<UUID>();
foreach (UUID tree in cp.m_trees)
{
SceneObjectPart sop = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
sop.Name = (freezeState ? sop.Name.Replace("ATPM", "FTPM") : sop.Name.Replace("FTPM", "ATPM"));
sop.ParentGroup.HasGroupChanged = true;
SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
if(sog != null && !sog.IsDeleted)
{
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);
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);
return;
}
}
}
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....");
lock(mylock)
{
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)
{
@ -306,8 +356,9 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
return;
}
}
m_copse.Add(copse);
}
m_copses.Add(copse);
}
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);
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_planted)
{
// 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;
return;
}
else
{
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();
Copse copseIdentity = null;
foreach (Copse cp in m_copse)
lock(mylock)
{
foreach (Copse cp in m_copses)
{
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);
}
}
copseIdentity.m_trees = new List<UUID>();
m_copse.Remove(copseIdentity);
copseIdentity.m_trees = null;
m_copses.Remove(copseIdentity);
m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename);
}
else
@ -408,11 +465,13 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename);
}
}
}
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);
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);
}
@ -442,7 +501,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double");
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 =
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.State = (byte)treeType;
return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape);
}
#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);
SceneObjectGroup sog = new SceneObjectGroup(uuid, position, rotation, treeShape);
SceneObjectPart rootPart = sog.RootPart;
rootPart.AddFlag(PrimFlags.Phantom);
sceneObject.SetGroup(groupID, null);
m_scene.AddNewSceneObject(sceneObject, true);
sceneObject.InvalidateEffectivePerms();
return sceneObject;
sog.SetGroup(groupID, null);
m_scene.AddNewSceneObject(sog, true, false);
sog.IsSelected = false;
rootPart.IsSelected = false;
sog.InvalidateEffectivePerms();
return sog;
}
#endregion
@ -569,14 +611,13 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
private void ReloadCopse()
{
m_copse = new List<Copse>();
m_copses = new List<Copse>();
EntityBase[] objs = m_scene.GetEntities();
foreach (EntityBase obj in objs)
List<SceneObjectGroup> grps = m_scene.GetSceneObjectGroups();
foreach (SceneObjectGroup grp in grps)
{
if (obj is SceneObjectGroup)
{
SceneObjectGroup grp = (SceneObjectGroup)obj;
if(grp.RootPart.Shape.PCode != (byte)PCode.NewTree && grp.RootPart.Shape.PCode != (byte)PCode.Tree)
continue;
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
{
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;
cp.m_trees.Add(grp.UUID);
@ -598,9 +641,10 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
if (!copsefound)
{
m_log.InfoFormat("[TREES]: Found copse {0}", grp.Name);
m_copse.Add(copse);
copse.m_trees.Add(grp.UUID);
m_log.InfoFormat("[TREES]: adding copse {0}", grpcopse.m_name);
grpcopse.m_trees.Add(grp.UUID);
m_copses.Add(grpcopse);
}
}
}
catch
@ -610,15 +654,16 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
}
}
}
}
#endregion
private void activeizeTreeze(bool activeYN)
{
if (activeYN)
{
if(CalculateTrees == null)
CalculateTrees = new Timer(m_update_ms);
CalculateTrees.Elapsed += CalculateTrees_Elapsed;
CalculateTrees.AutoReset = false;
CalculateTrees.Start();
}
else
@ -629,155 +674,252 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
private void growTrees()
{
foreach (Copse copse in m_copse)
{
if (!copse.m_frozen)
if(!m_allowGrow)
return;
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)
{
if (m_scene.Entities.ContainsKey(tree))
{
SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart;
SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
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;
s_tree.ParentGroup.HasGroupChanged = true;
SceneObjectPart s_tree = sog.RootPart;
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();
}
}
else
{
m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
}
}
losttrees.Add(tree);
}
foreach (UUID tree in losttrees)
copse.m_trees.Remove(tree);
}
}
private void seedTrees()
{
foreach (Copse copse in m_copse)
foreach (Copse copse in m_copses)
{
if (!copse.m_frozen)
{
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_frozen)
continue;
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
if (s_tree.Scale.Z > copse.m_initial_scale.Z + (copse.m_maximum_scale.Z - copse.m_initial_scale.Z) / 4.0)
{
if (Util.RandomClass.NextDouble() > 0.75)
{
SpawnChild(copse, s_tree);
}
}
}
}
else
{
m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree);
}
if (s_tree.Scale.Z > minscale)
SpawnChild(copse, s_tree, true);
}
else if(copse.m_trees.Contains(tree))
copse.m_trees.Remove(tree);
}
}
}
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)
{
foreach (UUID tree in copse.m_trees)
{
double killLikelyhood = 0.0;
if (copse.m_frozen)
continue;
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;
double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) +
Math.Pow(selectedTree.Scale.Y, 2) +
Math.Pow(selectedTree.Scale.Z, 2));
foreach (UUID picktree in copse.m_trees)
int next = 0;
if (copse.m_trees.Count > 1)
next = Util.RandomClass.Next(copse.m_trees.Count - 1);
UUID tree = copse.m_trees[next];
SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree);
if (sog != null && !sog.IsDeleted)
{
if (picktree != tree)
if(m_allowGrow)
{
SceneObjectPart pickedTree = ((SceneObjectGroup)m_scene.Entities[picktree]).RootPart;
double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) +
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;
odds = sog.RootPart.Scale.Z * scale;
odds = odds * odds * odds;
odds *= (float)Util.RandomClass.NextDouble();
}
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(selectedTree.ParentGroup, false);
copse.m_trees.Remove(selectedTree.ParentGroup.UUID);
m_scene.DeleteSceneObject(sog, false);
if(maxbdeaths <= 0)
break;
}
}
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();
double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3);
double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3);
float randX = copse.m_maximum_scale.X * 1.25f;
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;
r = (float)Util.RandomClass.NextDouble();
randY *= 2.0f * r - 1.0f;
position.Y = s_tree.AbsolutePosition.Y + (float)randY;
if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 &&
position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 &&
Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range)
{
if (position.X > (m_scene.RegionInfo.RegionSizeX - 1) || position.X <= 0 ||
position.Y > (m_scene.RegionInfo.RegionSizeY - 1) || position.Y <= 0)
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;
CreateTree(uuid, copse, position);
}
CreateTree(uuid, copse, position, low);
}
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];
if (position.Z >= copse.m_treeline_low && position.Z <= copse.m_treeline_high)
{
SceneObjectGroup tree = AddTree(uuid, UUID.Zero, copse.m_initial_scale, Quaternion.Identity, position, copse.m_tree_type, false);
if (position.Z < copse.m_treeline_low || position.Z > copse.m_treeline_high)
return;
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();
copse.m_trees.Add(tree.UUID);
tree.SendGroupFullUpdate();
}
tree.RootPart.ScheduleFullUpdate();
}
private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e)
{
if(!m_scene.IsRunning)
return;
if(Monitor.TryEnter(mylock))
{
try
{
if(m_scene.LoginsEnabled )
{
growTrees();
seedTrees();
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 runDivisor = 0.8f;
private bool flying = false;
private bool m_flying = false;
private bool m_iscolliding = false;
private bool m_iscollidingGround = false;
private bool m_iscollidingObj = false;
@ -298,10 +298,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
public override bool Flying
{
get { return flying; }
get { return m_flying; }
set
{
flying = value;
m_flying = value;
// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
}
}
@ -943,12 +943,13 @@ namespace OpenSim.Region.PhysicsModule.ubOde
}
return true;
}
/*
d.AABB aabb;
d.GeomGetAABB(other,out aabb);
float othertop = aabb.MaxZ - _position.Z;
*/
// if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f)
if (gtype == d.GeomClassID.SphereClass && d.GeomGetBody(other) != IntPtr.Zero)
{
if(d.GeomSphereGetRadius(other) < 0.5)
return true;
}
if (offset.Z > 0 || contact.normal.Z > 0.35f)
{
if (offset.Z <= 0)
@ -965,6 +966,18 @@ namespace OpenSim.Region.PhysicsModule.ubOde
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;
useAltcontact = true;
@ -972,8 +985,21 @@ namespace OpenSim.Region.PhysicsModule.ubOde
offset.Normalize();
if (contact.depth > 0.1f)
contact.depth = 0.1f;
float tdp = contact.depth;
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)
{
@ -987,15 +1013,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
altContact.normal.Y = -offset.Y;
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 false;
@ -1098,7 +1115,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
float ftmp;
if (flying)
if (m_flying)
{
ftmp = timeStep;
posch.X += vel.X * ftmp;
@ -1122,7 +1139,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
vec.Z = depth * PID_P * 50;
if (!flying)
if (!m_flying)
{
vec.Z += -vel.Z * PID_D;
if(n.Z < 0.4f)
@ -1259,7 +1276,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
// movement relative to surface if moving on it
// 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;
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 (tviszero && m_iscolliding && !flying)
if (tviszero && m_iscolliding && !m_flying)
{
// keep track of where we stopped. No more slippin' & slidin'
if (!_zeroFlag)
@ -1313,7 +1330,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_iscolliding)
{
if (!flying)
if (!m_flying)
{
// we are on a surface
if (ctz.Z > 0f)
@ -1361,7 +1378,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
}
else // ie not colliding
{
if (flying || hoverPIDActive) //(!m_iscolliding && flying)
if (m_flying || hoverPIDActive) //(!m_iscolliding && flying)
{
// we're in mid air suspended
vec.X += (ctz.X - vel.X) * (PID_D);
@ -1397,13 +1414,13 @@ namespace OpenSim.Region.PhysicsModule.ubOde
breakfactor = m_mass;
vec.X -= breakfactor * vel.X;
vec.Y -= breakfactor * vel.Y;
if (flying)
if (m_flying)
vec.Z -= 0.5f * breakfactor * vel.Z;
else
vec.Z -= .16f* m_mass * vel.Z;
}
if (flying || hoverPIDActive)
if (m_flying || hoverPIDActive)
{
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)
&& !rootPrim.m_isSelected && !rootPrim.m_disabled)
d.BodyEnable(rootPrim.Body);
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
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.BodySetAngularVel(Body, 0, 0, 0);
}
if(prim_geom != IntPtr.Zero)
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
disableBodySoft(); // stop collisions
UnSubscribeEvents();
@ -1240,7 +1241,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
SentEmptyCollisionsEvent = true;
// _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;
CollisionEventsThisFrame.Clear();
@ -1847,8 +1848,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
ApplyCollisionCatFlags();
_zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
resetCollisionAccounting();
@ -2900,6 +2901,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !m_disabled)
{
_zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
@ -2933,6 +2935,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (!d.BodyIsEnabled(Body))
{
_zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
@ -2947,6 +2950,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{
_zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
@ -3012,6 +3016,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{
_zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
@ -3070,6 +3075,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{
_zeroFlag = true;
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
@ -3312,8 +3318,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled)
enableBodySoft();
else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
m_torque = newtorque;
}
@ -3323,8 +3331,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde
{
m_force = force;
if (!m_isSelected && !m_outbounds && Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
private void changeAddForce(Vector3 theforce)
{
@ -3339,9 +3350,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled)
enableBodySoft();
else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
}
m_collisionscore = 0;
}
}
@ -3359,9 +3373,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled)
enableBodySoft();
else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
}
}
m_collisionscore = 0;
}
}
@ -3382,7 +3399,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled)
enableBodySoft();
else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
}
//resetCollisionAccounting();
@ -3406,7 +3426,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_disabled)
enableBodySoft();
else if (!d.BodyIsEnabled(Body))
{
d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames);
d.BodyEnable(Body);
}
d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
}
//resetCollisionAccounting();
@ -3571,12 +3594,13 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.BodySetAngularVel(Body,0f,0f,0f);
d.BodySetLinearVel(Body,0f,0f,0f);
_zeroFlag = true;
d.BodySetAutoDisableSteps(Body, 1);
d.BodyEnable(Body);
m_bodydisablecontrol = -4;
m_bodydisablecontrol = -3;
}
if(m_bodydisablecontrol < 0)
m_bodydisablecontrol ++;
m_bodydisablecontrol++;
d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
@ -3741,13 +3765,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
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)
return;
bool bodyenabled = d.BodyIsEnabled(Body);
if (bodyenabled || !_zeroFlag)
{
bool lastZeroFlag = _zeroFlag;

View File

@ -203,8 +203,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
private float metersInSpace = 25.6f;
private float m_timeDilation = 1.0f;
private DateTime m_lastframe;
private DateTime m_lastMeshExpire;
private double m_lastframe;
private double m_lastMeshExpire;
public float gravityx = 0f;
public float gravityy = 0f;
@ -481,7 +481,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision);
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_interval = physicsconfig.GetInt("physics_logging_interval", 0);
@ -629,8 +629,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
staticPrimspaceOffRegion[i] = newspace;
}
m_lastframe = DateTime.UtcNow;
m_lastframe = Util.GetTimeStamp();
m_lastMeshExpire = m_lastframe;
step_time = -1;
}
internal void waitForSpaceUnlock(IntPtr space)
@ -952,8 +953,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
SharedTmpcontact.surface.bounce = bounce;
d.ContactGeom altContact = new d.ContactGeom();
bool useAltcontact = false;
bool noskip = true;
bool useAltcontact;
bool noskip;
if(dop1ava || dop2ava)
smoothMesh = false;
@ -1000,7 +1001,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
Joint = CreateContacJoint(ref altContact,smoothMesh);
else
Joint = CreateContacJoint(ref curContact,smoothMesh);
if (Joint == IntPtr.Zero)
break;
@ -1626,6 +1626,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
}
m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count);
}
m_lastframe = Util.GetTimeStamp() + 0.5;
step_time = -0.5f;
}
/// <summary>
@ -1639,13 +1641,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde
/// <returns></returns>
public override float Simulate(float reqTimeStep)
{
DateTime now = DateTime.UtcNow;
TimeSpan timedif = now - m_lastframe;
float timeStep = (float)timedif.TotalSeconds;
double now = Util.GetTimeStamp();
double timeStep = now - m_lastframe;
m_lastframe = now;
// acumulate time so we can reduce error
step_time += timeStep;
step_time += (float)timeStep;
if (step_time < HalfOdeStep)
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
/*
int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
@ -1941,7 +1934,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
// if we lag too much skip frames
m_timeDilation = 0.0f;
step_time = 0;
m_lastframe = DateTime.UtcNow; // skip also the time lost
m_lastframe = Util.GetTimeStamp(); // skip also the time lost
}
else
{
@ -1949,6 +1942,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde
if (m_timeDilation > 1)
m_timeDilation = 1;
}
if (m_timeDilation == 1 && now - m_lastMeshExpire > 30)
{
mesher.ExpireReleaseMeshs();
m_lastMeshExpire = now;
}
}
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)
{
m_host.AddScriptLPS(1);
Util.FireAndForget(x =>
{
if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
return;
@ -3559,7 +3556,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
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 (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");
//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,
bool blend, int disp, int timer, int alpha, int face);
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,
int timer, int alpha);
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);
// Avatar Info Commands
string osGetAgentIP(string agent);
LSL_List osGetAgents();
string osGetAgentIP(string agent);
// Teleport commands
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 osDrawText(string drawList, string text);
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 osDrawFilledRectangle(string drawList, int width, int height);
string osDrawPolygon(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 osSetFontSize(string drawList, int fontSize);
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);
LSL_List osGetAvatarList();
LSL_List osGetNPCList();
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_AREA = 4;
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
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);
}
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,
int timer, int alpha)
{
@ -271,17 +277,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_OSSL_Functions.osTeleportOwner(position, lookat);
}
// Avatar info functions
public string osGetAgentIP(string agent)
{
return m_OSSL_Functions.osGetAgentIP(agent);
}
public LSL_List osGetAgents()
{
return m_OSSL_Functions.osGetAgents();
}
public string osGetAgentIP(string agent)
{
return m_OSSL_Functions.osGetAgentIP(agent);
}
// Animation Functions
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);
}
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)
{
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);
}
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)
{
return m_OSSL_Functions.osSetFontSize(drawList, fontSize);
@ -399,6 +429,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
return m_OSSL_Functions.osSetPenColor(drawList, color);
}
// Deprecated
public string osSetPenColour(string drawList, string colour)
{
@ -1010,6 +1041,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osGetAvatarList();
}
public LSL_List osGetNPCList()
{
return m_OSSL_Functions.osGetNPCList();
}
public LSL_String osUnixTimeToTimestamp(long time)
{
return m_OSSL_Functions.osUnixTimeToTimestamp(time);

View File

@ -39,7 +39,6 @@ using OMV_Quaternion = OpenMetaverse.Quaternion;
namespace OpenSim.Region.ScriptEngine.Shared
{
[Serializable]
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
@ -526,7 +525,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
}
[Serializable]
public class list
public class list: MarshalByRefObject
{
private object[] m_data;

View File

@ -109,6 +109,7 @@ namespace OpenSim.Tests.Common
public bool IsLandPrimCountTainted() { return false; }
public bool IsForcefulBansAllowed() { return false; }
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 setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) {}
public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) {}

View File

@ -118,8 +118,7 @@ namespace OpenSim.Tests.Stress
so.UUID,
m_tests.Vrm.GetContentType(),
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));

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]
; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying
; default is false
; enable the trees module. default true
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
; the trees change execution time rate (in ms)
update_rate = 1000
; Density of tree population
tree_density = 1000.0
; allow the trees to grow.
; DANGER
; this option causes high network use on the order of
; NumberOfTrees * NumberAvatars * 1000 / update_rate udp packets per second
allowGrow = false
[VectorRender]
; the font to use for rendering text (default: Arial)

View File

@ -31,7 +31,7 @@
; higher threat level OSSL functions, as detailed later on.
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 enable for everyone, set the value to 'true'.
; 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_GROUP_MEMBER" -- enable for any member of the parcel group
; 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
; 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.
; parcel macros
; 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
; ownership or group membership does not enable OSSL functions. Uncomment the
@ -62,49 +60,31 @@
; osslParcelO = "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.
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
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_osGetAvatarList = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetCurrentSunHour = true
Allow_osGetGender = true
Allow_osGetHealth = true
Allow_osGetHealRate = true
Allow_osGetInventoryDesc = true
Allow_osGetMapTexture = true
Allow_osGetRegionSize = true
Allow_osGetNPCList = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
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_osParseJSON = 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_osTeleportOwner = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osWindActiveModelPluginName = true
Allow_osCheckODE = true ; Here for completeness. This function cannot be turned off
; ThreatLevel Nuisance
Allow_osSetEstateSunSettings = ESTATE_MANAGER,ESTATE_OWNER
@ -114,11 +94,11 @@
Allow_osEjectFromGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osForceBreakAllLinks = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osForceBreakLink = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetDrawStringSize = true
Allow_osGetWindParam = true
Allow_osInviteToGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osReplaceString = true
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_osSetDynamicTextureDataBlendFace = ${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_osForceDropAttachment = ${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_osGetPhysicsEngineType = true
Allow_osGetPrimitiveParams = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
@ -238,3 +217,49 @@
Allow_osTeleportAgent = ${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.