diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index c5d7c47856..3db30d8647 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -1403,7 +1403,10 @@ namespace OpenSim.Data.MySQL
prim.Sound = DBGuid.FromDB(row["LoopedSound"].ToString());
prim.SoundGain = (float)(double)row["LoopedSoundGain"];
- prim.SoundFlags = 1; // If it's persisted at all, it's looped
+ if (prim.Sound != UUID.Zero)
+ prim.SoundFlags = 1; // If it's persisted at all, it's looped
+ else
+ prim.SoundFlags = 0;
if (!(row["TextureAnimation"] is DBNull))
prim.TextureAnimation = (byte[])row["TextureAnimation"];
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
index 569cc806a0..99ceb914e9 100755
--- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
+++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
@@ -1742,7 +1742,10 @@ namespace OpenSim.Data.PGSQL
prim.Sound = new UUID((Guid)primRow["LoopedSound"]);
prim.SoundGain = Convert.ToSingle(primRow["LoopedSoundGain"]);
- prim.SoundFlags = 1; // If it's persisted at all, it's looped
+ if (prim.Sound != UUID.Zero)
+ prim.SoundFlags = 1; // If it's persisted at all, it's looped
+ else
+ prim.SoundFlags = 0;
if (!(primRow["TextureAnimation"] is DBNull))
prim.TextureAnimation = (Byte[])primRow["TextureAnimation"];
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index e02ac7df2c..1403a8f8e5 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1742,7 +1742,10 @@ namespace OpenSim.Data.SQLite
prim.Sound = new UUID(row["LoopedSound"].ToString());
prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]);
- prim.SoundFlags = 1; // If it's persisted at all, it's looped
+ if (prim.Sound != UUID.Zero)
+ prim.SoundFlags = 1; // If it's persisted at all, it's looped
+ else
+ prim.SoundFlags = 0;
if (!row.IsNull("TextureAnimation"))
prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString());
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs
index 45c54e4989..1508c7f505 100644
--- a/OpenSim/Framework/ClientManager.cs
+++ b/OpenSim/Framework/ClientManager.cs
@@ -51,7 +51,14 @@ namespace OpenSim.Framework
private object m_syncRoot = new object();
/// Number of clients in the collection
- public int Count { get { return m_dict1.Count; } }
+ public int Count
+ {
+ get
+ {
+ lock (m_syncRoot)
+ return m_dict1.Count;
+ }
+ }
///
/// Default constructor
@@ -60,7 +67,7 @@ namespace OpenSim.Framework
{
m_dict1 = new Dictionary();
m_dict2 = new Dictionary();
- m_array = new IClientAPI[0];
+ m_array = null;
}
///
@@ -74,17 +81,9 @@ namespace OpenSim.Framework
{
lock (m_syncRoot)
{
- // allow self healing
-// if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint))
-// return false;
-
m_dict1[value.AgentId] = value;
m_dict2[value.RemoteEndPoint] = value;
-
- // dict1 is the master
- IClientAPI[] newArray = new IClientAPI[m_dict1.Count];
- m_dict1.Values.CopyTo(newArray, 0);
- m_array = newArray;
+ m_array = null;
}
return true;
@@ -105,10 +104,7 @@ namespace OpenSim.Framework
{
m_dict1.Remove(key);
m_dict2.Remove(value.RemoteEndPoint);
-
- IClientAPI[] newArray = new IClientAPI[m_dict1.Count];
- m_dict1.Values.CopyTo(newArray, 0);
- m_array = newArray;
+ m_array = null;
return true;
}
}
@@ -124,7 +120,7 @@ namespace OpenSim.Framework
{
m_dict1.Clear();
m_dict2.Clear();
- m_array = new IClientAPI[0];
+ m_array = null;
}
}
@@ -135,7 +131,8 @@ namespace OpenSim.Framework
/// True if the UUID was found in the collection, otherwise false
public bool ContainsKey(UUID key)
{
- return m_dict1.ContainsKey(key);
+ lock (m_syncRoot)
+ return m_dict1.ContainsKey(key);
}
///
@@ -145,7 +142,8 @@ namespace OpenSim.Framework
/// True if the endpoint was found in the collection, otherwise false
public bool ContainsKey(IPEndPoint key)
{
- return m_dict2.ContainsKey(key);
+ lock (m_syncRoot)
+ return m_dict2.ContainsKey(key);
}
///
@@ -156,8 +154,12 @@ namespace OpenSim.Framework
/// True if the lookup succeeded, otherwise false
public bool TryGetValue(UUID key, out IClientAPI value)
{
- try { return m_dict1.TryGetValue(key, out value); }
- catch (Exception)
+ try
+ {
+ lock (m_syncRoot)
+ return m_dict1.TryGetValue(key, out value);
+ }
+ catch
{
value = null;
return false;
@@ -172,8 +174,12 @@ namespace OpenSim.Framework
/// True if the lookup succeeded, otherwise false
public bool TryGetValue(IPEndPoint key, out IClientAPI value)
{
- try { return m_dict2.TryGetValue(key, out value); }
- catch (Exception)
+ try
+ {
+ lock (m_syncRoot)
+ return m_dict2.TryGetValue(key, out value);
+ }
+ catch
{
value = null;
return false;
@@ -187,7 +193,20 @@ namespace OpenSim.Framework
/// Action to perform on each element
public void ForEach(Action action)
{
- IClientAPI[] localArray = m_array;
+ IClientAPI[] localArray;
+ lock (m_syncRoot)
+ {
+ if (m_array == null)
+ {
+ if (m_dict1.Count == 0)
+ return;
+
+ m_array = new IClientAPI[m_dict1.Count];
+ m_dict1.Values.CopyTo(m_array, 0);
+ }
+ localArray = m_array;
+ }
+
for (int i = 0; i < localArray.Length; i++)
action(localArray[i]);
}
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 307dbf3917..d63136e332 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -390,7 +390,7 @@ namespace OpenSim.Framework
IClientAPI remoteClient, UUID invoice, UUID senderID, bool scripted, bool collisionEvents, bool physics);
public delegate void EstateTeleportOneUserHomeRequest(
- IClientAPI remoteClient, UUID invoice, UUID senderID, UUID prey);
+ IClientAPI remoteClient, UUID invoice, UUID senderID, UUID prey, bool kill);
public delegate void EstateTeleportAllUsersHomeRequest(IClientAPI remoteClient, UUID invoice, UUID senderID);
@@ -671,7 +671,6 @@ namespace OpenSim.Framework
Particles = 1 << 19,
ExtraData = 1 << 20,
Sound = 1 << 21,
- Joint = 1 << 22,
TerseUpdate = Position | Rotation | Velocity | Acceleration | AngularVelocity,
FullUpdate = 0x00ffffff,
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
old mode 100644
new mode 100755
index b9ac155401..14e21a2167
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -230,25 +230,25 @@ namespace OpenSim.Framework.Servers.HttpServer
PollServiceHttpRequest req;
while (m_running)
{
- req = null;
- if(!m_requests.TryTake(out req, 4500) || req == null)
- {
- Watchdog.UpdateThread();
- continue;
- }
-
- Watchdog.UpdateThread();
-
try
{
- if(!req.HttpContext.CanSend())
+ req = null;
+ if (!m_requests.TryTake(out req, 4500) || req == null)
+ {
+ Watchdog.UpdateThread();
+ continue;
+ }
+
+ Watchdog.UpdateThread();
+
+ if (!req.HttpContext.CanSend())
{
req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
byContextDequeue(req);
continue;
}
- if(req.HttpContext.IsSending())
+ if (req.HttpContext.IsSending())
{
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
@@ -256,7 +256,7 @@ namespace OpenSim.Framework.Servers.HttpServer
byContextDequeue(req);
}
else
- ReQueueEvent(req);
+ ReQueueEvent(req);
continue;
}
@@ -290,7 +290,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{
nreq.DoHTTPGruntWork(nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
}
- catch (ObjectDisposedException) {}
+ catch (ObjectDisposedException) { }
finally
{
byContextDequeue(nreq);
@@ -305,6 +305,12 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
}
+ catch (ThreadAbortException)
+ {
+ Thread.ResetAbort();
+ // Shouldn't set this to 'false', the normal shutdown should cause things to exit
+ // m_running = false;
+ }
catch (Exception e)
{
m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index 5604628d95..1a2d5d1e5f 100644
--- a/OpenSim/Framework/TerrainData.cs
+++ b/OpenSim/Framework/TerrainData.cs
@@ -212,7 +212,6 @@ namespace OpenSim.Framework
return heights;
}
- // TerrainData.GetDoubles
public double[,] GetDoubles()
{
double[,] ret = new double[SizeX, SizeY];
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 52f9aeab2b..f66a98736d 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -2437,34 +2437,6 @@ namespace OpenSim.Framework
#region FireAndForget Threading Pattern
- ///
- /// Created to work around a limitation in Mono with nested delegates
- ///
- private sealed class FireAndForgetWrapper
- {
- private static object syncRoot = new Object();
-
- public void FireAndForget(System.Threading.WaitCallback callback)
- {
- callback.BeginInvoke(null, EndFireAndForget, callback);
- }
-
- public void FireAndForget(System.Threading.WaitCallback callback, object obj)
- {
- callback.BeginInvoke(obj, EndFireAndForget, callback);
- }
-
- private static void EndFireAndForget(IAsyncResult ar)
- {
- System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
-
- try { callback.EndInvoke(ar); }
- catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
-
- ar.AsyncWaitHandle.Close();
- }
- }
-
public static void InitThreadPool(int minThreads, int maxThreads)
{
if (maxThreads < 2)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs
old mode 100644
new mode 100755
index 9187979903..c071bd1847
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.ClientStack.Linden
private string m_GetTextureURL;
private string m_GetMeshURL;
private string m_GetMesh2URL;
-// private string m_GetAssetURL;
+ private string m_GetAssetURL;
class APollRequest
{
@@ -87,7 +87,7 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary m_capsDictTexture = new Dictionary();
private Dictionary m_capsDictGetMesh = new Dictionary();
private Dictionary m_capsDictGetMesh2 = new Dictionary();
- //private Dictionary m_capsDictGetAsset = new Dictionary();
+ private Dictionary m_capsDictGetAsset = new Dictionary();
#region Region Module interfaceBase Members
@@ -113,11 +113,11 @@ namespace OpenSim.Region.ClientStack.Linden
m_GetMesh2URL = config.GetString("Cap_GetMesh2", string.Empty);
if (m_GetMesh2URL != string.Empty)
m_Enabled = true;
-/*
+
m_GetAssetURL = config.GetString("Cap_GetAsset", string.Empty);
if (m_GetAssetURL != string.Empty)
m_Enabled = true;
-*/
+
}
public void AddRegion(Scene pScene)
@@ -204,19 +204,26 @@ namespace OpenSim.Region.ClientStack.Linden
private static void DoAssetRequests()
{
- while (m_NumberScenes > 0)
+ try
{
- APollRequest poolreq;
- if(m_queue.TryTake(out poolreq, 4500))
+ while (m_NumberScenes > 0)
{
- if (m_NumberScenes <= 0)
- break;
+ APollRequest poolreq;
+ if (m_queue.TryTake(out poolreq, 4500))
+ {
+ if (m_NumberScenes <= 0)
+ break;
+ Watchdog.UpdateThread();
+ if (poolreq.reqID != UUID.Zero)
+ poolreq.thepoll.Process(poolreq);
+ poolreq = null;
+ }
Watchdog.UpdateThread();
- if (poolreq.reqID != UUID.Zero)
- poolreq.thepoll.Process(poolreq);
- poolreq = null;
}
- Watchdog.UpdateThread();
+ }
+ catch (ThreadAbortException)
+ {
+ Thread.ResetAbort();
}
}
@@ -441,7 +448,6 @@ namespace OpenSim.Region.ClientStack.Linden
else if (m_GetMesh2URL != string.Empty)
caps.RegisterHandler("GetMesh2", m_GetMesh2URL);
-/* we can't support this cap. Current viewers connect to the wrong regions.
//ViewerAsset
if (m_GetAssetURL == "localhost")
{
@@ -459,7 +465,7 @@ namespace OpenSim.Region.ClientStack.Linden
}
else if (m_GetAssetURL != string.Empty)
caps.RegisterHandler("ViewerAsset", m_GetMesh2URL);
-*/
+
}
private void DeregisterCaps(UUID agentID, Caps caps)
@@ -480,13 +486,12 @@ namespace OpenSim.Region.ClientStack.Linden
MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
m_capsDictGetMesh2.Remove(agentID);
}
-/*
+
if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl))
{
MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
m_capsDictGetAsset.Remove(agentID);
}
-*/
}
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
old mode 100644
new mode 100755
index 41d70a3ab9..9a01567064
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -395,17 +395,26 @@ namespace OpenSim.Region.ClientStack.Linden
private static void DoInventoryRequests()
{
- while (true)
+ bool running = true;
+ while (running)
{
- APollRequest poolreq;
- if (m_queue.TryTake(out poolreq, 4500))
+ try
{
+ APollRequest poolreq;
+ if (m_queue.TryTake(out poolreq, 4500))
+ {
+ Watchdog.UpdateThread();
+ if (poolreq.thepoll != null)
+ poolreq.thepoll.Process(poolreq);
+ poolreq = null;
+ }
Watchdog.UpdateThread();
- if (poolreq.thepoll != null)
- poolreq.thepoll.Process(poolreq);
- poolreq = null;
}
- Watchdog.UpdateThread();
+ catch (ThreadAbortException)
+ {
+ Thread.ResetAbort();
+ running = false;
+ }
}
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index b7d5a80dfd..ac041f500b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -1257,6 +1257,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SendLayerTopRight(x1 + 1, y1, x2, y2 - 1);
}
+ static private readonly byte[] TerrainPacketHeader = new byte[] {
+ Helpers.MSG_RELIABLE, // zero code is not as spec
+ 0, 0, 0, 0, // sequence number
+ 0, // extra
+ 11, // ID (high frequency)
+ };
+
+ private const int END_OF_PATCHES = 97;
+ private const int STRIDE = 264;
+
public void SendLayerData(int[] map)
{
if(map == null)
@@ -1264,9 +1274,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP
try
{
- List packets = OpenSimTerrainCompressor.CreateLayerDataPackets(m_scene.Heightmap.GetTerrainData(), map);
- foreach (LayerDataPacket pkt in packets)
- OutPacket(pkt, ThrottleOutPacketType.Land);
+ TerrainData terrData = m_scene.Heightmap.GetTerrainData();
+ byte landPacketType = (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) ?
+ (byte)TerrainPatch.LayerType.LandExtended : (byte)TerrainPatch.LayerType.Land;
+
+ int numberPatchs = map.Length / 2;
+
+ UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+ byte[] data = buf.Data;
+
+ Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
+
+ data[7] = landPacketType;
+ //data[8] and data[9] == datablock size to fill later
+
+ data[10] = 0; // BitPack needs this on reused packets
+
+ // start data
+ BitPack bitpack = new BitPack(data, 10);
+ bitpack.PackBits(STRIDE, 16);
+ bitpack.PackBitsFromByte(16);
+ bitpack.PackBitsFromByte(landPacketType);
+
+ int s;
+ int datasize = 0;
+ for (int i = 0; i < numberPatchs; i++)
+ {
+ s = 2 * i;
+ OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]);
+ if (bitpack.BytePos > 950 && i != numberPatchs - 1)
+ {
+ //finish this packet
+ bitpack.PackBitsFromByte(END_OF_PATCHES);
+
+ // fix the datablock lenght
+ datasize = bitpack.BytePos - 9;
+ data[8] = (byte)datasize;
+ data[9] = (byte)(datasize >> 8);
+
+ buf.DataLength = bitpack.BytePos + 1;
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
+
+ // start another
+ buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+ data = buf.Data;
+
+ Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
+
+ data[7] = landPacketType;
+ //data[8] and data[9] == datablock size to fill later
+
+ data[10] = 0; // BitPack needs this
+ // start data
+ bitpack = new BitPack(data, 10);
+
+ bitpack.PackBits(STRIDE, 16);
+ bitpack.PackBitsFromByte(16);
+ bitpack.PackBitsFromByte(landPacketType);
+ }
+ }
+
+ bitpack.PackBitsFromByte(END_OF_PATCHES);
+
+ datasize = bitpack.BytePos - 9;
+ data[8] = (byte)datasize;
+ data[9] = (byte)(datasize >> 8);
+
+ buf.DataLength = bitpack.BytePos + 1;
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
+
}
catch (Exception e)
{
@@ -1677,8 +1753,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendKillObject(List localIDs)
{
- // foreach (uint id in localIDs)
- // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
+ // foreach (uint id in localIDs)
+ // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
// remove pending entities to reduce looping chances.
lock (m_entityProps.SyncRoot)
@@ -1702,10 +1778,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if(++nsent >= 200)
{
- kill.Header.Reliable = true;
- kill.Header.Zerocoded = true;
OutPacket(kill, ThrottleOutPacketType.Task);
-
perpacket = localIDs.Count - i - 1;
if(perpacket == 0)
break;
@@ -1720,8 +1793,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if(nsent != 0)
{
- kill.Header.Reliable = true;
- kill.Header.Zerocoded = true;
OutPacket(kill, ThrottleOutPacketType.Task);
}
}
@@ -3832,32 +3903,136 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
}
+/*
public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
{
// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
// TODO: don't create new blocks if recycling an old packet
- ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length];
ani.Sender = new AvatarAnimationPacket.SenderBlock();
ani.Sender.ID = sourceAgentId;
ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0];
- for (int i = 0; i < animations.Length; ++i)
+ //self animations
+ if (sourceAgentId == AgentId)
{
- ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
- ani.AnimationList[i].AnimID = animations[i];
- ani.AnimationList[i].AnimSequenceID = seqs[i];
+ List withobjects = new List(animations.Length);
+ List noobjects = new List(animations.Length);
+ for(int i = 0; i < animations.Length; ++i)
+ {
+ if(objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
+ noobjects.Add(i);
+ else
+ withobjects.Add(i);
+ }
- ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock();
- if (objectIDs[i].Equals(sourceAgentId))
- ani.AnimationSourceList[i].ObjectID = UUID.Zero;
- else
- ani.AnimationSourceList[i].ObjectID = objectIDs[i];
+ ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[withobjects.Count];
+ int k = 0;
+ foreach (int i in withobjects)
+ {
+ ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
+ ani.AnimationList[k].AnimID = animations[i];
+ ani.AnimationList[k].AnimSequenceID = seqs[i];
+ ani.AnimationSourceList[k] = new AvatarAnimationPacket.AnimationSourceListBlock();
+ ani.AnimationSourceList[k].ObjectID = objectIDs[i];
+ k++;
+ }
+ foreach (int i in noobjects)
+ {
+ ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
+ ani.AnimationList[k].AnimID = animations[i];
+ ani.AnimationList[k].AnimSequenceID = seqs[i];
+ k++;
+ }
}
+ else
+ {
+ ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[0];
+ for (int i = 0; i < animations.Length; ++i)
+ {
+ ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
+ ani.AnimationList[i].AnimID = animations[i];
+ ani.AnimationList[i].AnimSequenceID = seqs[i];
+ }
+ }
+
OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
}
+*/
+
+ static private readonly byte[] AvatarAnimationHeader = new byte[] {
+ Helpers.MSG_RELIABLE,
+ 0, 0, 0, 0, // sequence number
+ 0, // extra
+ 20 // ID (high frequency)
+ };
+
+ public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
+ {
+ // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
+
+ UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+ byte[] data = buf.Data;
+ //setup header
+ Buffer.BlockCopy(AvatarAnimationHeader, 0, data, 0, 7);
+ //agent block
+ sourceAgentId.ToBytes(data, 7);
+
+ // animations count
+ data[23] = (byte)animations.Length;
+
+ int pos = 24;
+
+ //self animations
+ if (sourceAgentId == AgentId)
+ {
+ List withobjects = new List(animations.Length);
+ List noobjects = new List(animations.Length);
+ for (int i = 0; i < animations.Length; ++i)
+ {
+ if (objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
+ noobjects.Add(i);
+ else
+ withobjects.Add(i);
+ }
+
+ // first the ones with corresponding objects
+ foreach (int i in withobjects)
+ {
+ animations[i].ToBytes(data, pos); pos += 16;
+ Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
+ }
+ // then the rest
+ foreach (int i in noobjects)
+ {
+ animations[i].ToBytes(data, pos); pos += 16;
+ Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
+ }
+ // object ids block
+ data[pos++] = (byte)withobjects.Count;
+ foreach (int i in withobjects)
+ {
+ objectIDs[i].ToBytes(data, pos); pos += 16;
+ }
+ }
+ else
+ {
+ for(int i = 0; i < animations.Length; ++i)
+ {
+ animations[i].ToBytes(data, pos); pos += 16;
+ Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
+ }
+ data[pos++] = 0; // no object ids
+ }
+
+ data[pos++] = 0; // no physical avatar events
+
+ buf.DataLength = pos;
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority,
+ null, false, false);
+ }
public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId)
{
@@ -3889,36 +4064,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public void SendEntityFullUpdateImmediate(ISceneEntity ent)
{
-// m_log.DebugFormat(
-// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}",
-// avatar.Name, avatar.UUID, Name, AgentId);
-
- if (ent == null)
+ if (ent == null || (!(ent is ScenePresence) && !(ent is SceneObjectPart)))
return;
- ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
- objupdate.Header.Zerocoded = true;
+ UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+ Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
- objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
- objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
+ LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
+ zc.Position = 7;
- if(ent is ScenePresence)
+ zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
+ zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
+
+ zc.AddByte(1); // block count
+
+ ThrottleOutPacketType ptype = ThrottleOutPacketType.Task;
+ if (ent is ScenePresence)
{
- ScenePresence presence = ent as ScenePresence;
- objupdate.RegionData.RegionHandle = presence.RegionHandle;
- objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
- }
- else if(ent is SceneObjectPart)
- {
- SceneObjectPart part = ent as SceneObjectPart;
- objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
- objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent);
+ CreateAvatarUpdateBlock(ent as ScenePresence, zc);
+ ptype |= ThrottleOutPacketType.HighPriority;
}
+ else
+ CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc);
- OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
-
- // We need to record the avatar local id since the root prim of an attachment points to this.
-// m_attachmentsSent.Add(avatar.LocalId);
+ buf.DataLength = zc.Finish();
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ptype , null, false, false);
}
public void SendEntityTerseUpdateImmediate(ISceneEntity ent)
@@ -4089,6 +4259,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ResendPrimUpdate(update);
}
+ static private readonly byte[] objectUpdateHeader = new byte[] {
+ Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
+ 0, 0, 0, 0, // sequence number
+ 0, // extra
+ 12 // ID (high frequency)
+ };
+
+ static private readonly byte[] terseUpdateHeader = new byte[] {
+ Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec
+ 0, 0, 0, 0, // sequence number
+ 0, // extra
+ 15 // ID (high frequency)
+ };
+
private void ProcessEntityUpdates(int maxUpdatesBytes)
{
if (!IsActive)
@@ -4098,14 +4282,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (mysp == null)
return;
- List objectUpdateBlocks = null;
- List compressedUpdateBlocks = null;
- List terseUpdateBlocks = null;
- List terseAgentUpdateBlocks = null;
+ // List compressedUpdateBlocks = null;
List objectUpdates = null;
- List compressedUpdates = null;
+ // List compressedUpdates = null;
List terseUpdates = null;
- List terseAgentUpdates = null;
List ObjectAnimationUpdates = null;
// Check to see if this is a flush
@@ -4120,10 +4300,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
float cullingrange = 64.0f;
Vector3 mypos = Vector3.Zero;
- bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
+ //bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
+ bool orderedDequeue = false; // temporary off
HashSet GroupsNeedFullUpdate = new HashSet();
+
if (doCulling)
{
cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f;
@@ -4179,7 +4361,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
if (grp.IsAttachment)
- { // Someone else's HUD, why are we getting these?
+ {
+ // animated attachments are nasty if not supported by viewer
+ if(!m_SupportObjectAnimations && grp.RootPart.Shape.MeshFlagEntry)
+ continue;
+
+ // Someone else's HUD, why are we getting these?
if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint)
continue;
@@ -4273,7 +4460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if(ObjectAnimationUpdates == null)
ObjectAnimationUpdates = new List();
ObjectAnimationUpdates.Add(sop);
- maxUpdatesBytes -= 32 * sop.Animations.Count + 16;
+ maxUpdatesBytes -= 20 * sop.Animations.Count + 24;
}
}
}
@@ -4304,7 +4491,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
PrimUpdateFlags.Velocity |
PrimUpdateFlags.Acceleration |
PrimUpdateFlags.AngularVelocity |
- PrimUpdateFlags.CollisionPlane
+ PrimUpdateFlags.CollisionPlane |
+ PrimUpdateFlags.Textures
);
#endregion UpdateFlags to packet type conversion
@@ -4326,48 +4514,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if ((updateFlags & canNotUseImprovedMask) == 0)
{
- ImprovedTerseObjectUpdatePacket.ObjectDataBlock ablock =
- CreateImprovedTerseBlock(update.Entity);
+ if (terseUpdates == null)
+ {
+ terseUpdates = new List();
+ maxUpdatesBytes -= 18;
+ }
+ terseUpdates.Add(update);
if (update.Entity is ScenePresence)
- {
- // ALL presence updates go into a special list
- if (terseAgentUpdateBlocks == null)
- {
- terseAgentUpdateBlocks = new List();
- terseAgentUpdates = new List();
- }
- terseAgentUpdateBlocks.Add(ablock);
- terseAgentUpdates.Add(update);
- }
+ maxUpdatesBytes -= 63; // no texture entry
else
{
- // Everything else goes here
- if (terseUpdateBlocks == null)
- {
- terseUpdateBlocks = new List();
- terseUpdates = new List();
- }
- terseUpdateBlocks.Add(ablock);
- terseUpdates.Add(update);
+ if ((updateFlags & PrimUpdateFlags.Textures) == 0)
+ maxUpdatesBytes -= 47;
+ else
+ maxUpdatesBytes -= 150; // aprox
}
- maxUpdatesBytes -= ablock.Length;
}
else
{
- ObjectUpdatePacket.ObjectDataBlock ablock;
if (update.Entity is ScenePresence)
- ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
+ maxUpdatesBytes -= 150; // crude estimation
else
- ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp);
- if(objectUpdateBlocks == null)
+ maxUpdatesBytes -= 300;
+
+ if(objectUpdates == null)
{
- objectUpdateBlocks = new List();
objectUpdates = new List();
+ maxUpdatesBytes -= 18;
}
- objectUpdateBlocks.Add(ablock);
objectUpdates.Add(update);
- maxUpdatesBytes -= ablock.Length;
}
#endregion Block Construction
@@ -4382,29 +4558,87 @@ namespace OpenSim.Region.ClientStack.LindenUDP
timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
- if (terseAgentUpdateBlocks != null)
+ if(objectUpdates != null)
{
- ImprovedTerseObjectUpdatePacket packet
- = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
- packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
- packet.RegionData.TimeDilation = timeDilation;
- packet.ObjectData = terseAgentUpdateBlocks.ToArray();
- terseAgentUpdateBlocks.Clear();
+ int blocks = objectUpdates.Count;
+ List tau = new List(30);
- OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates, oPacket); });
- }
-
- if (objectUpdateBlocks != null)
- {
- ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
- packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
- packet.RegionData.TimeDilation = timeDilation;
- packet.ObjectData = objectUpdateBlocks.ToArray();
- objectUpdateBlocks.Clear();
-
- OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates, oPacket); });
+ UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+ Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
+
+ LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
+ zc.Position = 7;
+
+ zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
+ zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
+
+ zc.AddByte(1); // tmp block count
+
+ int countposition = zc.Position - 1;
+
+ int lastpos = 0;
+ int lastzc = 0;
+
+ int count = 0;
+ foreach (EntityUpdate eu in objectUpdates)
+ {
+ lastpos = zc.Position;
+ lastzc = zc.ZeroCount;
+ if (eu.Entity is ScenePresence)
+ CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
+ else
+ CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
+ if (zc.Position < LLUDPServer.MAXPAYLOAD)
+ {
+ tau.Add(eu);
+ ++count;
+ --blocks;
+ }
+ else if (blocks > 0)
+ {
+ // we need more packets
+ UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+ Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
+
+ buf.Data[countposition] = (byte)count;
+ // get pending zeros at cut point
+ if(lastzc > 0)
+ {
+ buf.Data[lastpos++] = 0;
+ buf.Data[lastpos++] = (byte)lastzc;
+ }
+ buf.DataLength = lastpos;
+
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
+ delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
+
+ buf = newbuf;
+ zc.Data = buf.Data;
+ zc.ZeroCount = 0;
+ zc.Position = countposition + 1;
+ // im lazy now, just do last again
+ if (eu.Entity is ScenePresence)
+ CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
+ else
+ CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
+
+ tau = new List(30);
+ tau.Add(eu);
+ count = 1;
+ --blocks;
+ }
+ }
+
+ if (count > 0)
+ {
+ buf.Data[countposition] = (byte)count;
+ buf.DataLength = zc.Finish();
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
+ delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
+ }
}
+/*
if (compressedUpdateBlocks != null)
{
ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
@@ -4415,20 +4649,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); });
}
-
- if (terseUpdateBlocks != null)
+*/
+ if (terseUpdates != null)
{
- ImprovedTerseObjectUpdatePacket packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
- PacketType.ImprovedTerseObjectUpdate);
- packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
- packet.RegionData.TimeDilation = timeDilation;
- packet.ObjectData = terseUpdateBlocks.ToArray();
- terseUpdateBlocks.Clear();
+ int blocks = terseUpdates.Count;
+ List tau = new List(30);
- OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates, oPacket); });
+ UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+
+ //setup header and regioninfo block
+ Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
+ Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
+ Utils.UInt16ToBytes(timeDilation, buf.Data, 15);
+ int pos = 18;
+ int lastpos = 0;
+
+ int count = 0;
+ foreach (EntityUpdate eu in terseUpdates)
+ {
+ lastpos = pos;
+ CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, (eu.Flags & PrimUpdateFlags.Textures) != 0);
+ if (pos < LLUDPServer.MAXPAYLOAD)
+ {
+ tau.Add(eu);
+ ++count;
+ --blocks;
+ }
+ else if (blocks > 0)
+ {
+ // we need more packets
+ UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
+ Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same
+ // copy what we done in excess
+ int extralen = pos - lastpos;
+ if(extralen > 0)
+ Buffer.BlockCopy(buf.Data, lastpos, newbuf.Data, 18, extralen);
+
+ pos = 18 + extralen;
+
+ buf.Data[17] = (byte)count;
+ buf.DataLength = lastpos;
+ // zero encode is not as spec
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
+ delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
+
+ tau = new List(30);
+ tau.Add(eu);
+ count = 1;
+ --blocks;
+ buf = newbuf;
+ }
+ }
+
+ if (count > 0)
+ {
+ buf.Data[17] = (byte)count;
+ buf.DataLength = pos;
+ m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
+ delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
+ }
}
- if(ObjectAnimationUpdates != null)
+ if (ObjectAnimationUpdates != null)
{
foreach (SceneObjectPart sop in ObjectAnimationUpdates)
{
@@ -4445,13 +4727,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
UUID[] ids = null;
int[] seqs = null;
int count = sop.GetAnimations(out ids, out seqs);
- if(count < 0)
- continue;
ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
ani.Sender = new ObjectAnimationPacket.SenderBlock();
ani.Sender.ID = sop.UUID;
- ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count];
+ ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count];
for(int i = 0; i< count; i++)
{
@@ -4642,9 +4922,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// These are used to implement an adaptive backoff in the number
// of updates converted to packets. Since we don't want packets
// to sit in the queue with old data, only convert enough updates
- // to packets that can be sent in 200ms.
-// private Int32 m_LastQueueFill = 0;
-// private Int32 m_maxUpdates = 0;
+ // to packets that can be sent in 30ms.
void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
{
@@ -5645,9 +5923,144 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return block;
}
+ protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
+ {
+ #region ScenePresence/SOP Handling
+
+ bool avatar = (entity is ScenePresence);
+ uint localID = entity.LocalId;
+ uint attachPoint;
+ Vector4 collisionPlane;
+ Vector3 position, velocity, acceleration, angularVelocity;
+ Quaternion rotation;
+ byte datasize;
+ byte[] te = null;
+
+ if (avatar)
+ {
+ ScenePresence presence = (ScenePresence)entity;
+
+ position = presence.OffsetPosition;
+ velocity = presence.Velocity;
+ acceleration = Vector3.Zero;
+ rotation = presence.Rotation;
+ // tpvs can only see rotations around Z in some cases
+ if (!presence.Flying && !presence.IsSatOnObject)
+ {
+ rotation.X = 0f;
+ rotation.Y = 0f;
+ }
+ rotation.Normalize();
+ angularVelocity = presence.AngularVelocity;
+
+ // m_log.DebugFormat(
+ // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
+
+ attachPoint = presence.State;
+ collisionPlane = presence.CollisionPlane;
+
+ datasize = 60;
+ }
+ else
+ {
+ SceneObjectPart part = (SceneObjectPart)entity;
+
+ attachPoint = part.ParentGroup.AttachmentPoint;
+ attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
+ // m_log.DebugFormat(
+ // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
+ // attachPoint, part.Name, part.LocalId, Name);
+
+ collisionPlane = Vector4.Zero;
+ position = part.RelativePosition;
+ velocity = part.Velocity;
+ acceleration = part.Acceleration;
+ angularVelocity = part.AngularVelocity;
+ rotation = part.RotationOffset;
+
+ datasize = 44;
+ if(includeTexture)
+ te = part.Shape.TextureEntry;
+ }
+
+ #endregion ScenePresence/SOP Handling
+ //object block size
+ data[pos++] = datasize;
+
+ // LocalID
+ Utils.UIntToBytes(localID, data, pos);
+ pos += 4;
+
+ data[pos++] = (byte)attachPoint;
+
+ // Avatar/CollisionPlane
+ if (avatar)
+ {
+ data[pos++] = 1;
+
+ if (collisionPlane == Vector4.Zero)
+ collisionPlane = Vector4.UnitW;
+ //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
+ collisionPlane.ToBytes(data, pos);
+ pos += 16;
+ }
+ else
+ {
+ data[pos++] = 0;
+ }
+
+ // Position
+ position.ToBytes(data, pos);
+ pos += 12;
+
+ // Velocity
+ ClampVectorForUint(ref velocity, 128f);
+ Utils.FloatToUInt16Bytes(velocity.X, 128.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(velocity.Y, 128.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(velocity.Z, 128.0f, data, pos); pos += 2;
+
+ // Acceleration
+ ClampVectorForUint(ref acceleration, 64f);
+ Utils.FloatToUInt16Bytes(acceleration.X, 64.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(acceleration.Y, 64.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2;
+
+ // Rotation
+ Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2;
+
+ // Angular Velocity
+ ClampVectorForUint(ref angularVelocity, 64f);
+ Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2;
+ Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2;
+
+ // texture entry block size
+ if(te == null)
+ {
+ data[pos++] = 0;
+ data[pos++] = 0;
+ }
+ else
+ {
+ int len = te.Length & 0x7fff;
+ int totlen = len + 4;
+ data[pos++] = (byte)totlen;
+ data[pos++] = (byte)(totlen >> 8);
+ data[pos++] = (byte)len; // wtf ???
+ data[pos++] = (byte)(len >> 8);
+ data[pos++] = 0;
+ data[pos++] = 0;
+ Buffer.BlockCopy(te, 0, data, pos, len);
+ pos += len;
+ }
+ // total size 63 or 47 + (texture size + 4)
+ }
+
protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
{
- Vector3 offsetPosition = data.OffsetPosition;
Quaternion rotation = data.Rotation;
// tpvs can only see rotations around Z in some cases
if(!data.Flying && !data.IsSatOnObject)
@@ -5657,27 +6070,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
rotation.Normalize();
- uint parentID = data.ParentID;
-
// m_log.DebugFormat(
// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
byte[] objectData = new byte[76];
- Vector3 velocity = new Vector3(0, 0, 0);
- Vector3 acceleration = new Vector3(0, 0, 0);
+ //Vector3 velocity = Vector3.Zero;
+ Vector3 acceleration = Vector3.Zero;
+ Vector3 angularvelocity = Vector3.Zero;
data.CollisionPlane.ToBytes(objectData, 0);
- offsetPosition.ToBytes(objectData, 16);
- velocity.ToBytes(objectData, 28);
+ data.OffsetPosition.ToBytes(objectData, 16);
+ data.Velocity.ToBytes(objectData, 28);
acceleration.ToBytes(objectData, 40);
rotation.ToBytes(objectData, 52);
- data.AngularVelocity.ToBytes(objectData, 64);
+ angularvelocity.ToBytes(objectData, 64);
ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
update.Data = Utils.EmptyBytes;
- update.ExtraParams = new byte[1];
+ update.ExtraParams = Utils.EmptyBytes;
update.FullID = data.UUID;
update.ID = data.LocalId;
update.Material = (byte)Material.Flesh;
@@ -5714,7 +6126,158 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return update;
}
-// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
+ protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos)
+ {
+ Quaternion rotation = data.Rotation;
+ // tpvs can only see rotations around Z in some cases
+ if (!data.Flying && !data.IsSatOnObject)
+ {
+ rotation.X = 0f;
+ rotation.Y = 0f;
+ }
+ rotation.Normalize();
+
+ //Vector3 velocity = Vector3.Zero;
+ //Vector3 acceleration = Vector3.Zero;
+ //Vector3 angularvelocity = Vector3.Zero;
+
+ Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;
+ dest[pos++] = 0; // state
+ data.UUID.ToBytes(dest, pos); pos += 16;
+ Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc
+ dest[pos++] = (byte)PCode.Avatar;
+ dest[pos++] = (byte)Material.Flesh;
+ dest[pos++] = 0; // clickaction
+ data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12;
+
+ // objectdata block
+ dest[pos++] = 76;
+ data.CollisionPlane.ToBytes(dest, pos); pos += 16;
+ data.OffsetPosition.ToBytes(dest, pos); pos += 12;
+ data.Velocity.ToBytes(dest, pos); pos += 12;
+
+ //acceleration.ToBytes(dest, pos); pos += 12;
+ Array.Clear(dest, pos, 12); pos += 12;
+
+ rotation.ToBytes(dest, pos); pos += 12;
+
+ //angularvelocity.ToBytes(dest, pos); pos += 12;
+ Array.Clear(dest, pos, 12); pos += 12;
+
+ SceneObjectPart parentPart = data.ParentPart;
+ if (parentPart != null)
+ {
+ Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos);
+ pos += 4;
+ }
+ else
+ {
+// Utils.UIntToBytesSafepos(0, dest, pos);
+// pos += 4;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+ }
+
+ //Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+
+ //pbs
+ dest[pos++] = 16;
+ dest[pos++] = 1;
+ //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
+ //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+ dest[pos++] = 0;
+
+ dest[pos++] = 100;
+ dest[pos++] = 100;
+
+ // rest of pbs is 0 (15), texture entry (2) and texture anim (1)
+ const int pbszeros = 15 + 2 + 1;
+ Array.Clear(dest, pos, pbszeros); pos += pbszeros;
+
+ //NameValue
+ byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
+ data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
+ int len = nv.Length;
+ dest[pos++] = (byte)len;
+ dest[pos++] = (byte)(len >> 8);
+ Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len;
+
+ // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
+ // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
+ // jointtype(1) joint pivot(12) joint offset(12)
+ const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
+ Array.Clear(dest, pos, lastzeros); pos += lastzeros;
+ }
+
+ protected void CreateAvatarUpdateBlock(ScenePresence data, LLUDPZeroEncoder zc)
+ {
+ Quaternion rotation = data.Rotation;
+ // tpvs can only see rotations around Z in some cases
+ if (!data.Flying && !data.IsSatOnObject)
+ {
+ rotation.X = 0f;
+ rotation.Y = 0f;
+ }
+ rotation.Normalize();
+
+ zc.AddUInt(data.LocalId);
+ zc.AddByte(0);
+ zc.AddUUID(data.UUID);
+ zc.AddZeros(4); // crc unused
+ zc.AddByte((byte)PCode.Avatar);
+ zc.AddByte((byte)Material.Flesh);
+ zc.AddByte(0); // clickaction
+ zc.AddVector3(data.Appearance.AvatarSize);
+
+ // objectdata block
+ zc.AddByte(76); // fixed avatar block size
+ zc.AddVector4(data.CollisionPlane);
+ zc.AddVector3(data.OffsetPosition);
+ zc.AddVector3(data.Velocity);
+ //zc.AddVector3(acceleration);
+ zc.AddZeros(12);
+ zc.AddNormQuat(rotation);
+ //zc.AddVector3(angularvelocity);
+ zc.AddZeros(12);
+
+ SceneObjectPart parentPart = data.ParentPart;
+ if (parentPart != null)
+ zc.AddUInt(parentPart.ParentGroup.LocalId);
+ else
+ zc.AddZeros(4);
+
+ zc.AddZeros(4); //update flags
+
+ //pbs volume data 23
+ //texture entry 2
+ //texture anim (1)
+ const int pbszeros = 23 + 2 + 1;
+ zc.AddZeros(pbszeros);
+
+ //NameValue
+ byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
+ data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
+ int len = nv.Length;
+ zc.AddByte((byte)len);
+ zc.AddByte((byte)(len >> 8));
+ zc.AddBytes(nv, len);
+
+ // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
+ // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
+ // jointtype(1) joint pivot(12) joint offset(12)
+ const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
+ zc.AddZeros(lastzeros);
+ }
+
protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp)
{
byte[] objectData = new byte[60];
@@ -5737,32 +6300,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//update.JointPivot = Vector3.Zero;
//update.JointType = 0;
update.Material = part.Material;
-/*
- if (data.ParentGroup.IsAttachment)
- {
- update.NameValue
- = Util.StringToBytes256(
- string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID));
-
- update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16));
-
-// m_log.DebugFormat(
-// "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}",
-// Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name);
-//
-// m_log.DebugFormat(
-// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}",
-// update.State, data.Name, data.LocalId, Name);
- }
- else
- {
- update.NameValue = Utils.EmptyBytes;
-
- // The root part state is the canonical state for all parts of the object. The other part states in the
- // case for attachments may contain conflicting values that can end up crashing the viewer.
- update.State = data.ParentGroup.RootPart.Shape.State;
- }
-*/
if (part.ParentGroup.IsAttachment)
{
@@ -5858,15 +6395,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion PrimFlags
- if (part.Sound != UUID.Zero || part.SoundFlags != 0)
+ bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
+ if (hassound)
{
update.Sound = part.Sound;
- update.OwnerID = part.OwnerID;
update.Gain = (float)part.SoundGain;
update.Radius = (float)part.SoundRadius;
update.Flags = part.SoundFlags;
}
+ if(hassound || update.PSBlock.Length > 1)
+ update.OwnerID = part.OwnerID;
+
switch ((PCode)part.Shape.PCode)
{
case PCode.Grass:
@@ -5882,6 +6422,308 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return update;
}
+ protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc)
+ {
+ // prepare data
+
+ #region PrimFlags
+ // prim/update flags
+ PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
+ // Don't send the CreateSelected flag to everyone
+ primflags &= ~PrimFlags.CreateSelected;
+ if (sp.UUID == part.OwnerID)
+ {
+ if (part.CreateSelected)
+ {
+ // Only send this flag once, then unset it
+ primflags |= PrimFlags.CreateSelected;
+ part.CreateSelected = false;
+ }
+ }
+ #endregion PrimFlags
+
+ // data block
+ byte[] data = null;
+ byte state = part.Shape.State;
+ PCode pcode = (PCode)part.Shape.PCode;
+
+ //vegetation is special so just do it inline
+ if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
+ {
+ zc.AddUInt(part.LocalId);
+ zc.AddByte(state); // state
+ zc.AddUUID(part.UUID);
+ zc.AddZeros(4); // crc unused
+ zc.AddByte((byte)pcode);
+ // material 1
+ // clickaction 1
+ zc.AddZeros(2);
+ zc.AddVector3(part.Shape.Scale);
+
+ // objectdata block
+ zc.AddByte(60); // fixed object block size
+ zc.AddVector3(part.RelativePosition);
+ if (pcode == PCode.Grass)
+ zc.AddZeros(48);
+ else
+ {
+ zc.AddZeros(24);
+ Quaternion rot = part.RotationOffset;
+ rot.Normalize();
+ zc.AddNormQuat(rot);
+ zc.AddZeros(12);
+ }
+
+ zc.AddUInt(part.ParentID);
+ zc.AddUInt((uint)primflags); //update flags
+
+ /*
+ if (pcode == PCode.Grass)
+ {
+ //pbs volume data 23
+ //texture entry 2
+ //texture anim 1
+ //name value 2
+ // data 1
+ // text 5
+ // media url 1
+ // particle system 1
+ // Extraparams 1
+ // sound id 16
+ // ownwer 16
+ // sound gain 4
+ // sound flags 1
+ // sound radius 4
+ // jointtype 1
+ // joint pivot 12
+ // joint offset 12
+ zc.AddZeros(23 + 2 + 1 + 2 + 1 + 5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
+ return;
+ }
+ */
+
+ //pbs volume data 23
+ //texture entry 2
+ //texture anim 1
+ //name value 2
+ zc.AddZeros(23 + 2 + 1 + 2);
+
+ //data: the tree type
+ zc.AddByte(1);
+ zc.AddZeros(1);
+ zc.AddByte(state);
+
+ // text 5
+ // media url 1
+ // particle system 1
+ // Extraparams 1
+ // sound id 16
+ // ownwer 16
+ // sound gain 4
+ // sound flags 1
+ // sound radius 4
+ // jointtype 1
+ // joint pivot 12
+ // joint offset 12
+ zc.AddZeros(5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
+
+ return;
+ }
+
+ //NameValue and state
+ byte[] nv = null;
+
+ if (part.ParentGroup.IsAttachment)
+ {
+ if (part.IsRoot)
+ nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID);
+
+ int st = (int)part.ParentGroup.AttachmentPoint;
+ state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
+ }
+
+ // filter out mesh faces hack
+ ushort profileBegin = part.Shape.ProfileBegin;
+ ushort profileHollow = part.Shape.ProfileHollow;
+ byte profileCurve = part.Shape.ProfileCurve;
+ byte pathScaleY = part.Shape.PathScaleY;
+
+ if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
+ {
+ profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
+ // fix old values that confused viewers
+ if (profileBegin == 1)
+ profileBegin = 9375;
+ if (profileHollow == 1)
+ profileHollow = 27500;
+ // fix torus hole size Y that also confuse some viewers
+ if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
+ pathScaleY = 150;
+ }
+
+ // do encode the things
+ zc.AddUInt(part.LocalId);
+ zc.AddByte(state); // state
+ zc.AddUUID(part.UUID);
+ zc.AddZeros(4); // crc unused
+ zc.AddByte((byte)pcode);
+ zc.AddByte(part.Material);
+ zc.AddByte(part.ClickAction); // clickaction
+ zc.AddVector3(part.Shape.Scale);
+
+ // objectdata block
+ zc.AddByte(60); // fixed object block size
+ zc.AddVector3(part.RelativePosition);
+ zc.AddVector3(part.Velocity);
+ zc.AddVector3(part.Acceleration);
+ Quaternion rotation = part.RotationOffset;
+ rotation.Normalize();
+ zc.AddNormQuat(rotation);
+ zc.AddVector3(part.AngularVelocity);
+
+ zc.AddUInt(part.ParentID);
+ zc.AddUInt((uint)primflags); //update flags
+
+ //pbs
+ zc.AddByte(part.Shape.PathCurve);
+ zc.AddByte(profileCurve);
+ zc.AddUInt16(part.Shape.PathBegin);
+ zc.AddUInt16(part.Shape.PathEnd);
+ zc.AddByte(part.Shape.PathScaleX);
+ zc.AddByte(pathScaleY);
+ zc.AddByte(part.Shape.PathShearX);
+ zc.AddByte(part.Shape.PathShearY);
+ zc.AddByte((byte)part.Shape.PathTwist);
+ zc.AddByte((byte)part.Shape.PathTwistBegin);
+ zc.AddByte((byte)part.Shape.PathRadiusOffset);
+ zc.AddByte((byte)part.Shape.PathTaperX);
+ zc.AddByte((byte)part.Shape.PathTaperY);
+ zc.AddByte(part.Shape.PathRevolutions);
+ zc.AddByte((byte)part.Shape.PathSkew);
+ zc.AddUInt16(profileBegin);
+ zc.AddUInt16(part.Shape.ProfileEnd);
+ zc.AddUInt16(profileHollow);
+
+ // texture
+ byte[] tentry = part.Shape.TextureEntry;
+ if (tentry == null)
+ zc.AddZeros(2);
+ else
+ {
+ int len = tentry.Length;
+ zc.AddByte((byte)len);
+ zc.AddByte((byte)(len >> 8));
+ zc.AddBytes(tentry, len);
+ }
+
+ // texture animation
+ byte[] tanim = part.TextureAnimation;
+ if (tanim == null)
+ zc.AddZeros(1);
+ else
+ {
+ int len = tanim.Length;
+ zc.AddByte((byte)len);
+ zc.AddBytes(tanim, len);
+ }
+
+ //NameValue
+ if(nv == null)
+ zc.AddZeros(2);
+ else
+ {
+ int len = nv.Length;
+ zc.AddByte((byte)len);
+ zc.AddByte((byte)(len >> 8));
+ zc.AddBytes(nv, len);
+ }
+
+ // data
+ if (data == null)
+ zc.AddZeros(2);
+ else
+ {
+ int len = data.Length;
+ zc.AddByte((byte)len);
+ zc.AddByte((byte)(len >> 8));
+ zc.AddBytes(data, len);
+ }
+
+ //text
+ if (part.Text == null || part.Text.Length == 0)
+ zc.AddZeros(5);
+ else
+ {
+ byte[] tbuf = Util.StringToBytes(part.Text, 254);
+ int len = tbuf.Length;
+ zc.AddByte((byte)len);
+ zc.AddBytes(tbuf, len);
+
+ //textcolor
+ byte[] tc = part.GetTextColor().GetBytes(false);
+ zc.AddBytes(tc, 4);
+ }
+
+ //media url
+ if (part.MediaUrl == null || part.MediaUrl.Length == 0)
+ zc.AddZeros(1);
+ else
+ {
+ byte[] tbuf = Util.StringToBytes(part.MediaUrl, 255);
+ int len = tbuf.Length;
+ zc.AddByte((byte)len);
+ zc.AddBytes(tbuf, len);
+ }
+
+ bool hasps = false;
+ //particle system
+ byte[] ps = part.ParticleSystem;
+ if (ps == null || ps.Length < 1)
+ zc.AddZeros(1);
+ else
+ {
+ int len = ps.Length;
+ zc.AddByte((byte)len);
+ zc.AddBytes(ps, len);
+ hasps = true;
+ }
+
+ //Extraparams
+ byte[] ep = part.Shape.ExtraParams;
+ if (ep == null || ep.Length < 2)
+ zc.AddZeros(1);
+ else
+ {
+ int len = ep.Length;
+ zc.AddByte((byte)len);
+ zc.AddBytes(ep, len);
+ }
+
+ bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
+ if (hassound)
+ zc.AddUUID(part.Sound);
+ else
+ zc.AddZeros(16);
+
+ if (hassound || hasps)
+ zc.AddUUID(part.OwnerID);
+ else
+ zc.AddZeros(16);
+
+ if (hassound)
+ {
+ zc.AddFloat((float)part.SoundGain);
+ zc.AddByte(part.SoundFlags);
+ zc.AddFloat((float)part.SoundRadius);
+ }
+ else
+ zc.AddZeros(9);
+
+ // jointtype(1) joint pivot(12) joint offset(12)
+ const int lastzeros = 1 + 12 + 12;
+ zc.AddZeros(lastzeros);
+ }
+
protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
{
// TODO: Implement this
@@ -10047,7 +10889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey);
- OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey);
+ OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, false);
}
return true;
case "teleporthomeallusers":
@@ -10195,7 +11037,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey);
- OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey);
+ OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, true);
}
return true;
@@ -12560,14 +13402,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// provide your own method.
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
{
-
-/* this is causing packet loss for some reason
- if(!m_udpClient.IsConnected)
- {
- PacketPool.Instance.ReturnPacket(packet);
- return;
- }
-*/
if (m_outPacketsToDrop != null)
{
if (m_outPacketsToDrop.Contains(packet.Type.ToString()))
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 439621ae4e..2981337b2d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -120,7 +120,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Circuit code that this client is connected on
public readonly uint CircuitCode;
/// Sequence numbers of packets we've received (for duplicate checking)
- public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
+ public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256);
/// Packets we have sent that need to be ACKed by the client
public UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
@@ -210,12 +210,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
- ///
- /// This is the percentage of the udp texture queue to add to the task queue since
- /// textures are now generally handled through http.
- ///
- private double m_cannibalrate = 0.0;
-
private ClientInfo m_info = new ClientInfo();
///
@@ -257,8 +251,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Create an array of token buckets for this clients different throttle categories
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
- m_cannibalrate = rates.CannibalizeTextureRate;
-
m_burst = rates.Total * rates.BrustTime;
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
@@ -449,12 +441,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
asset = Math.Max(asset, LLUDPServer.MTU);
*/
- // Since most textures are now delivered through http, make it possible
- // to cannibalize some of the bw from the texture throttle to use for
- // the task queue (e.g. object updates)
- task = task + (int)(m_cannibalrate * texture);
- texture = (int)((1 - m_cannibalrate) * texture);
-
int total = resend + land + wind + cloud + task + texture + asset;
float m_burst = total * m_burstTime;
@@ -575,22 +561,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
DoubleLocklessQueue queue = m_packetOutboxes[category];
- if (m_deliverPackets == false)
+ if (forceQueue || m_deliverPackets == false)
{
queue.Enqueue(packet, highPriority);
return true;
}
- TokenBucket bucket = m_throttleCategories[category];
-
- // Don't send this packet if queue is not empty
+ // need to enqueue if queue is not empty
if (queue.Count > 0 || m_nextPackets[category] != null)
{
queue.Enqueue(packet, highPriority);
return true;
}
- if (!forceQueue && bucket.CheckTokens(packet.Buffer.DataLength))
+ // check bandwidth
+ TokenBucket bucket = m_throttleCategories[category];
+ if (bucket.CheckTokens(packet.Buffer.DataLength))
{
// enough tokens so it can be sent imediatly by caller
bucket.RemoveTokens(packet.Buffer.DataLength);
@@ -608,7 +594,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// We don't have a token bucket for this category, so it will not be queued
return false;
}
-
}
///
@@ -650,6 +635,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// leaving a dequeued packet still waiting to be sent out. Try to
// send it again
OutgoingPacket nextPacket = m_nextPackets[i];
+ if(nextPacket.Buffer == null)
+ {
+ if (m_packetOutboxes[i].Count < 5)
+ emptyCategories |= CategoryToFlag(i);
+ continue;
+ }
if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
{
// Send the packet
@@ -681,21 +672,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
// A packet was pulled off the queue. See if we have
// enough tokens in the bucket to send it out
- if (bucket.RemoveTokens(packet.Buffer.DataLength))
+ if(packet.Buffer == null)
{
- // Send the packet
- m_udpServer.SendPacketFinal(packet);
- packetSent = true;
-
+ // packet canceled elsewhere (by a ack for example)
if (queue.Count < 5)
emptyCategories |= CategoryToFlag(i);
}
else
{
- // Save the dequeued packet for the next iteration
- m_nextPackets[i] = packet;
- }
+ if (bucket.RemoveTokens(packet.Buffer.DataLength))
+ {
+ // Send the packet
+ m_udpServer.SendPacketFinal(packet);
+ packetSent = true;
+ if (queue.Count < 5)
+ emptyCategories |= CategoryToFlag(i);
+ }
+ else
+ {
+ // Save the dequeued packet for the next iteration
+ m_nextPackets[i] = packet;
+ }
+ }
}
else
{
@@ -803,8 +802,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
-
-
///
/// Fires the OnQueueEmpty callback and sets the minimum time that it
/// can be called again
@@ -843,6 +840,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return 0;
}
+ public void FreeUDPBuffer(UDPPacketBuffer buf)
+ {
+ m_udpServer.FreeUDPBuffer(buf);
+ }
+
///
/// Converts a integer to a
/// flag value
@@ -853,34 +855,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
ThrottleOutPacketType category = (ThrottleOutPacketType)i;
- /*
- * Land = 1,
- /// Wind data
- Wind = 2,
- /// Cloud data
- Cloud = 3,
- /// Any packets that do not fit into the other throttles
- Task = 4,
- /// Texture assets
- Texture = 5,
- /// Non-texture assets
- Asset = 6,
- */
-
switch (category)
{
case ThrottleOutPacketType.Land:
- return ThrottleOutPacketTypeFlags.Land;
+ return ThrottleOutPacketTypeFlags.Land; // Terrain data
case ThrottleOutPacketType.Wind:
- return ThrottleOutPacketTypeFlags.Wind;
+ return ThrottleOutPacketTypeFlags.Wind; // Wind data
case ThrottleOutPacketType.Cloud:
- return ThrottleOutPacketTypeFlags.Cloud;
+ return ThrottleOutPacketTypeFlags.Cloud; // Cloud data
case ThrottleOutPacketType.Task:
- return ThrottleOutPacketTypeFlags.Task;
+ return ThrottleOutPacketTypeFlags.Task; // Object updates and everything not on the other categories
case ThrottleOutPacketType.Texture:
- return ThrottleOutPacketTypeFlags.Texture;
+ return ThrottleOutPacketTypeFlags.Texture; // Textures data (also impacts http texture and mesh by default)
case ThrottleOutPacketType.Asset:
- return ThrottleOutPacketTypeFlags.Asset;
+ return ThrottleOutPacketTypeFlags.Asset; // Non-texture Assets data
default:
return 0;
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
old mode 100644
new mode 100755
index 35d29a5adb..2300800f57
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -256,6 +256,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Maximum transmission unit, or UDP packet size, for the LLUDP protocol
public const int MTU = 1400;
+ public const int MAXPAYLOAD = 1250;
/// Number of forced client logouts due to no receipt of packets before timeout.
public int ClientLogoutsDueToNoReceives { get; protected set; }
@@ -274,10 +275,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// The measured resolution of Environment.TickCount
public readonly float TickCountResolution;
- /// Number of prim updates to put on the queue each time the
- /// OnQueueEmpty event is triggered for updates
- public readonly int PrimUpdatesPerCallback;
-
/// Number of texture packets to put on the queue each time the
/// OnQueueEmpty event is triggered for textures
public readonly int TextureSendLimit;
@@ -344,18 +341,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected ExpiringCache> m_pendingCache = new ExpiringCache>();
- protected Pool m_incomingPacketPool;
-
- ///
- /// Stat for number of packets in the main pool awaiting use.
- ///
- protected Stat m_poolCountStat;
-
- ///
- /// Stat for number of packets in the inbound packet pool awaiting use.
- ///
- protected Stat m_incomingPacketPoolStat;
-
protected int m_defaultRTO = 0;
protected int m_maxRTO = 0;
protected int m_ackTimeout = 0;
@@ -452,7 +437,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
- PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
TextureSendLimit = config.GetInt("TextureSendLimit", 20);
m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -463,7 +447,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
else
{
- PrimUpdatesPerCallback = 100;
TextureSendLimit = 20;
m_ackTimeout = 1000 * 60; // 1 minute
m_pausedAckTimeout = 1000 * 300; // 5 minutes
@@ -498,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// if (usePools)
// EnablePools();
- base.DisablePools();
}
public void Start()
@@ -554,83 +536,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OqrEngine.Stop();
}
- public override bool EnablePools()
- {
- if (!UsePools)
- {
- base.EnablePools();
-
- m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500);
-
- return true;
- }
-
- return false;
- }
-
- public override bool DisablePools()
- {
- if (UsePools)
- {
- base.DisablePools();
-
- StatsManager.DeregisterStat(m_incomingPacketPoolStat);
-
- // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
-
- return true;
- }
-
- return false;
- }
-
- ///
- /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
- /// stats.
- ///
- protected internal void EnablePoolStats()
- {
- m_poolCountStat
- = new Stat(
- "UDPPacketBufferPoolCount",
- "Objects within the UDPPacketBuffer pool",
- "The number of objects currently stored within the UDPPacketBuffer pool",
- "",
- "clientstack",
- Scene.Name,
- StatType.Pull,
- stat => stat.Value = Pool.Count,
- StatVerbosity.Debug);
-
- StatsManager.RegisterStat(m_poolCountStat);
-
- m_incomingPacketPoolStat
- = new Stat(
- "IncomingPacketPoolCount",
- "Objects within incoming packet pool",
- "The number of objects currently stored within the incoming packet pool",
- "",
- "clientstack",
- Scene.Name,
- StatType.Pull,
- stat => stat.Value = m_incomingPacketPool.Count,
- StatVerbosity.Debug);
-
- StatsManager.RegisterStat(m_incomingPacketPoolStat);
- }
-
- ///
- /// Disables pool stats.
- ///
- protected internal void DisablePoolStats()
- {
- StatsManager.DeregisterStat(m_poolCountStat);
- m_poolCountStat = null;
-
- StatsManager.DeregisterStat(m_incomingPacketPoolStat);
- m_incomingPacketPoolStat = null;
- }
-
///
/// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
///
@@ -658,8 +563,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name),
"INCOMING PACKET ASYNC HANDLING ENGINE");
*/
- OqrEngine
- = new JobEngine(
+ OqrEngine = new JobEngine(
string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
"OUTGOING QUEUE REFILL ENGINE");
@@ -769,15 +673,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
stat => stat.Value = OqrEngine.JobsWaiting,
StatVerbosity.Debug));
- // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by
- // scene name
- if (UsePools)
- EnablePoolStats();
-
+ StatsManager.RegisterStat(
+ new Stat(
+ "UDPBuffersPoolCount",
+ "Buffers in the UDP buffers pool",
+ "The number of buffers currently stored within the UDP buffers pool",
+ "",
+ "clientstack",
+ Scene.Name,
+ StatType.Pull,
+ stat => stat.Value = m_udpBuffersPoolPtr + 1,
+ StatVerbosity.Debug));
LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
commands.Register();
-
}
public bool HandlesRegion(Location x)
@@ -939,9 +848,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
// there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
// to accomodate for both common scenarios and provide ample room for ACK appending in both
- int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
+ //int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
- UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
+ //UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
+ UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
// Zerocode if needed
if (doZerocode)
@@ -971,7 +881,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// If the packet data wasn't already copied during zerocoding, copy it now
if (doCopy)
{
- if (dataLength <= buffer.Data.Length)
+ //if (dataLength <= buffer.Data.Length)
+ if (dataLength <= LLUDPServer.MTU)
{
Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
}
@@ -979,7 +890,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
- buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength);
+ // buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength);
+ buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
}
}
@@ -1017,6 +929,89 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion Queue or Send
}
+ public unsafe UDPPacketBuffer ZeroEncode(UDPPacketBuffer input)
+ {
+ UDPPacketBuffer zb = GetNewUDPBuffer(null);
+ int srclen = input.DataLength;
+ byte[] src = input.Data;
+ byte[] dest = zb.Data;
+
+ int zerolen = 6;
+ byte zerocount = 0;
+
+ for (int i = zerolen; i < srclen; i++)
+ {
+ if (src[i] == 0x00)
+ {
+ zerocount++;
+ if (zerocount == 0)
+ {
+ dest[zerolen++] = 0x00;
+ dest[zerolen++] = 0xff;
+ zerocount++;
+ }
+ }
+ else
+ {
+ if (zerocount != 0)
+ {
+ dest[zerolen++] = 0x00;
+ dest[zerolen++] = zerocount;
+ zerocount = 0;
+ }
+
+ dest[zerolen++] = src[i];
+ }
+ }
+
+ if (zerocount != 0)
+ {
+ dest[zerolen++] = 0x00;
+ dest[zerolen++] = zerocount;
+ }
+
+ if(zerolen >= srclen)
+ {
+ FreeUDPBuffer(zb);
+
+ src[0] &= unchecked((byte)~Helpers.MSG_ZEROCODED);
+ return input;
+ }
+
+ Buffer.BlockCopy(src, 0, dest, 0, 6);
+
+ zb.RemoteEndPoint = input.RemoteEndPoint;
+ zb.DataLength = zerolen;
+
+ FreeUDPBuffer(input);
+
+ return zb;
+ }
+
+ public void SendUDPPacket(
+ LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode)
+ {
+ bool highPriority = false;
+
+ if(zerocode)
+ buffer = ZeroEncode(buffer);
+
+ if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
+ {
+ category = (ThrottleOutPacketType)((int)category & 127);
+ highPriority = true;
+ }
+
+ OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
+
+ // If we were not provided a method for handling unacked, use the UDPServer default method
+ if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
+ outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
+
+ if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forcequeue, highPriority))
+ SendPacketFinal(outgoingPacket);
+ }
+
public void SendAcks(LLUDPClient udpClient)
{
uint ack;
@@ -1066,7 +1061,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
LLUDPClient udpClient = client.UDPClient;
- if (!udpClient.IsConnected)
+ if (!client.IsActive || !udpClient.IsConnected)
return;
// Disconnect an agent if no packets are received for some time
@@ -1136,14 +1131,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
internal void SendPacketFinal(OutgoingPacket outgoingPacket)
{
UDPPacketBuffer buffer = outgoingPacket.Buffer;
+ if(buffer == null) // canceled packet
+ return;
+ LLUDPClient udpClient = outgoingPacket.Client;
+ if (!udpClient.IsConnected)
+ return;
+
byte flags = buffer.Data[0];
bool isResend = (flags & Helpers.MSG_RESENT) != 0;
bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
- LLUDPClient udpClient = outgoingPacket.Client;
-
- if (!udpClient.IsConnected)
- return;
int dataLength = buffer.DataLength;
@@ -1154,7 +1151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// no more ACKs to append
int ackCount = 0;
uint ack;
- while (dataLength + 5 < buffer.Data.Length && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack))
+ while (dataLength + 5 < MTU && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack))
{
Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
dataLength += 4;
@@ -1168,22 +1165,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Set the appended ACKs flag on this packet
buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
}
+ buffer.DataLength = dataLength;
}
- buffer.DataLength = dataLength;
-
if (!isResend)
{
// Not a resend, assign a new sequence number
uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
outgoingPacket.SequenceNumber = sequenceNumber;
-
- if (isReliable)
- {
- // Add this packet to the list of ACK responses we are waiting on from the server
- udpClient.NeedAcks.Add(outgoingPacket);
- }
}
else
{
@@ -1196,9 +1186,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
PacketsSentCount++;
SyncSend(buffer);
+
// Keep track of when this packet was sent out (right now)
outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
+ if (outgoingPacket.UnackedMethod == null)
+ FreeUDPBuffer(buffer);
+ else if(!isResend)
+ {
+ // Add this packet to the list of ACK responses we are waiting on from the server
+ udpClient.NeedAcks.Add(outgoingPacket);
+ }
+
if (udpClient.DebugDataOutLevel > 0)
m_log.DebugFormat(
"[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}",
@@ -1240,7 +1239,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
RecordMalformedInboundPacket(endPoint);
-
+ FreeUDPBuffer(buffer);
return; // Drop undersized packet
}
@@ -1260,21 +1259,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
RecordMalformedInboundPacket(endPoint);
-
+ FreeUDPBuffer(buffer);
return; // Malformed header
}
try
{
-// packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
-// // Only allocate a buffer for zerodecoding if the packet is zerocoded
-// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
+ // get a buffer for zero decode using the udp buffers pool
+ UDPPacketBuffer zerodecodebufferholder = null;
+ byte[] zerodecodebuffer = null;
+ // only if needed
+ if (((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0))
+ {
+ zerodecodebufferholder = GetNewUDPBuffer(null);
+ zerodecodebuffer = zerodecodebufferholder.Data;
+ }
+
+ packet = Packet.BuildPacket(buffer.Data, ref packetEnd, zerodecodebuffer);
// If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
// assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
// bytes are copied out).
- packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
- // Only allocate a buffer for zerodecoding if the packet is zerocoded
- ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
+ // packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, zerodecodebuffer);
+ if(zerodecodebufferholder != null)
+ FreeUDPBuffer(zerodecodebufferholder);
}
catch (Exception e)
{
@@ -1292,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
RecordMalformedInboundPacket(endPoint);
-
+ FreeUDPBuffer(buffer);
return;
}
@@ -1311,17 +1318,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
lock (m_pendingCache)
{
if (m_pendingCache.Contains(endPoint))
+ {
+ FreeUDPBuffer(buffer);
return;
+ }
m_pendingCache.AddOrUpdate(endPoint, new Queue(), 60);
}
- // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
- // buffer.
- object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
-
- Util.FireAndForget(HandleUseCircuitCode, array);
-
+ Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet });
+ FreeUDPBuffer(buffer);
return;
}
}
@@ -1336,24 +1342,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
queue.Enqueue(buffer);
return;
}
-
-/*
- else if (packet.Type == PacketType.CompleteAgentMovement)
- {
- // Send ack straight away to let the viewer know that we got it.
- SendAckImmediate(endPoint, packet.Header.Sequence);
-
- // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
- // buffer.
- object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
-
- Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
-
- return;
- }
- */
}
+ FreeUDPBuffer(buffer);
+
// Determine which agent this packet came from
if (client == null || !(client is LLClientView))
{
@@ -1471,10 +1463,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
#endregion BinaryStats
-
-//AgentUpdate removed from here
-
-
#region Ping Check Handling
if (packet.Type == PacketType.StartPingCheck)
@@ -1506,17 +1494,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
IncomingPacket incomingPacket;
- // Inbox insertion
- if (UsePools)
- {
- incomingPacket = m_incomingPacketPool.GetObject();
- incomingPacket.Client = (LLClientView)client;
- incomingPacket.Packet = packet;
- }
- else
- {
- incomingPacket = new IncomingPacket((LLClientView)client, packet);
- }
+ incomingPacket = new IncomingPacket((LLClientView)client, packet);
// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
@@ -1525,7 +1503,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// else
// packetInbox.Enqueue(incomingPacket);
packetInbox.Add(incomingPacket);
-
}
#region BinaryStats
@@ -1685,7 +1662,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
return;
-
}
m_pendingCache.Remove(endPoint);
}
@@ -1881,13 +1857,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
byte[] packetData = ack.ToBytes();
int length = packetData.Length;
- UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);
+ UDPPacketBuffer buffer = GetNewUDPBuffer(remoteEndpoint);
buffer.DataLength = length;
Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
// AsyncBeginSend(buffer);
SyncSend(buffer);
+ FreeUDPBuffer(buffer);
}
protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
@@ -1982,21 +1959,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Scene.ThreadAlive(1);
try
{
- packetInbox.TryTake(out incomingPacket, 250);
+ packetInbox.TryTake(out incomingPacket, 4500);
if (incomingPacket != null && IsRunningInbound)
{
ProcessInPacket(incomingPacket);
-
- if (UsePools)
- {
- incomingPacket.Client = null;
- m_incomingPacketPool.ReturnObject(incomingPacket);
- }
incomingPacket = null;
}
}
- catch(Exception ex)
+ catch (ThreadAbortException)
+ {
+ Thread.ResetAbort();
+ }
+ catch (Exception ex)
{
m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
}
@@ -2025,7 +2000,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
Scene.ThreadAlive(2);
-
try
{
m_packetSent = false;
@@ -2080,7 +2054,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
else if (!m_packetSent)
// Thread.Sleep((int)TickCountResolution); outch this is bad on linux
- Thread.Sleep(15); // match the 16ms of windows7, dont ask 16 or win may decide to do 32ms.
+ Thread.Sleep(15); // match the 16ms of windows, dont ask 16 or win may decide to do 32ms.
Watchdog.UpdateThread();
}
@@ -2104,14 +2078,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (udpClient.IsConnected)
{
- if (m_resendUnacked)
+ if (client.IsActive && m_resendUnacked)
HandleUnacked(llClient);
- if (m_sendAcks)
- SendAcks(udpClient);
+ if (client.IsActive)
+ {
+ if (m_sendAcks)
+ SendAcks(udpClient);
- if (m_sendPing)
- SendPing(udpClient);
+ if (m_sendPing)
+ SendPing(udpClient);
+ }
// Dequeue any outgoing packets that are within the throttle limits
if (udpClient.DequeueOutgoing())
@@ -2124,7 +2101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_log.Error(
string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
}
- client = null;
}
#region Emergency Monitoring
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
index 012a57d969..a4d7eb924e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
@@ -777,41 +777,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_udpServer.StopOutbound();
}
- private void HandlePoolCommand(string module, string[] args)
- {
- if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
- return;
-
- if (args.Length != 4)
- {
- MainConsole.Instance.Output("Usage: debug lludp pool ");
- return;
- }
-
- string enabled = args[3];
-
- if (enabled == "on")
- {
- if (m_udpServer.EnablePools())
- {
- m_udpServer.EnablePoolStats();
- MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_udpServer.Scene.Name);
- }
- }
- else if (enabled == "off")
- {
- if (m_udpServer.DisablePools())
- {
- m_udpServer.DisablePoolStats();
- MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_udpServer.Scene.Name);
- }
- }
- else
- {
- MainConsole.Instance.Output("Usage: debug lludp pool ");
- }
- }
-
private void HandleAgentUpdateCommand(string module, string[] args)
{
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
@@ -834,8 +799,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
MainConsole.Instance.OutputFormat(
"OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled");
- MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_udpServer.Scene.Name, m_udpServer.UsePools ? "on" : "off");
-
MainConsole.Instance.OutputFormat(
"Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel);
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs
new file mode 100644
index 0000000000..8ed2cf12cd
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using OpenSim.Framework;
+using Nini.Config;
+using OpenMetaverse;
+
+namespace OpenSim.Region.ClientStack.LindenUDP
+{
+ public sealed class LLUDPZeroEncoder
+ {
+ private byte[] m_tmp = new byte[16];
+ private byte[] m_dest;
+ private int zerocount;
+ private int pos;
+
+ public LLUDPZeroEncoder()
+ {
+ }
+
+ public LLUDPZeroEncoder(byte[] data)
+ {
+ m_dest = data;
+ zerocount = 0;
+ }
+
+ public byte[] Data
+ {
+ get
+ {
+ return m_dest;
+ }
+ set
+ {
+ m_dest = value;
+ }
+ }
+
+ public int ZeroCount
+ {
+ get
+ {
+ return zerocount;
+ }
+ set
+ {
+ zerocount = value;
+ }
+ }
+
+ public int Position
+ {
+ get
+ {
+ return pos;
+ }
+ set
+ {
+ pos = value;
+ }
+ }
+
+ public unsafe void AddZeros(int len)
+ {
+ zerocount += len;
+ while (zerocount > 255)
+ {
+ m_dest[pos++] = 0x00;
+ m_dest[pos++] = 0xff;
+ zerocount -= 256;
+ }
+ }
+
+ public unsafe int Finish()
+ {
+ if(zerocount > 0)
+ {
+ m_dest[pos++] = 0x00;
+ m_dest[pos++] = (byte)zerocount;
+ }
+ return pos;
+ }
+
+ public unsafe void AddBytes(byte[] src, int srclen)
+ {
+ for (int i = 0; i < srclen; ++i)
+ {
+ if (src[i] == 0x00)
+ {
+ zerocount++;
+ if (zerocount == 0)
+ {
+ m_dest[pos++] = 0x00;
+ m_dest[pos++] = 0xff;
+ zerocount++;
+ }
+ }
+ else
+ {
+ if (zerocount != 0)
+ {
+ m_dest[pos++] = 0x00;
+ m_dest[pos++] = (byte)zerocount;
+ zerocount = 0;
+ }
+
+ m_dest[pos++] = src[i];
+ }
+ }
+ }
+
+ public unsafe void AddByte(byte v)
+ {
+ if (v == 0x00)
+ {
+ zerocount++;
+ if (zerocount == 0)
+ {
+ m_dest[pos++] = 0x00;
+ m_dest[pos++] = 0xff;
+ zerocount++;
+ }
+ }
+ else
+ {
+ if (zerocount != 0)
+ {
+ m_dest[pos++] = 0x00;
+ m_dest[pos++] = (byte)zerocount;
+ zerocount = 0;
+ }
+
+ m_dest[pos++] = v;
+ }
+ }
+
+ public void AddInt16(short v)
+ {
+ if (v == 0)
+ AddZeros(2);
+ else
+ {
+ Utils.Int16ToBytes(v, m_tmp, 0);
+ AddBytes(m_tmp, 2);
+ }
+ }
+
+ public void AddUInt16(ushort v)
+ {
+ if (v == 0)
+ AddZeros(2);
+ else
+ {
+ Utils.UInt16ToBytes(v, m_tmp, 0);
+ AddBytes(m_tmp, 2);
+ }
+ }
+
+ public void AddInt(int v)
+ {
+ if (v == 0)
+ AddZeros(4);
+ else
+ {
+ Utils.IntToBytesSafepos(v, m_tmp, 0);
+ AddBytes(m_tmp, 4);
+ }
+ }
+
+ public unsafe void AddUInt(uint v)
+ {
+ if (v == 0)
+ AddZeros(4);
+ else
+ {
+ Utils.UIntToBytesSafepos(v, m_tmp, 0);
+ AddBytes(m_tmp, 4);
+ }
+ }
+
+ public void AddFloatToUInt16(float v, float range)
+ {
+ Utils.FloatToUInt16Bytes(v, range, m_tmp, 0);
+ AddBytes(m_tmp, 2);
+ }
+
+ public void AddFloat(float v)
+ {
+ if (v == 0f)
+ AddZeros(4);
+ else
+ {
+ Utils.FloatToBytesSafepos(v, m_tmp, 0);
+ AddBytes(m_tmp, 4);
+ }
+ }
+
+ public void AddInt64(long v)
+ {
+ if (v == 0)
+ AddZeros(8);
+ else
+ {
+ Utils.Int64ToBytesSafepos(v, m_tmp, 0);
+ AddBytes(m_tmp, 8);
+ }
+ }
+
+ public void AddUInt64(ulong v)
+ {
+ if (v == 0)
+ AddZeros(8);
+ else
+ {
+ Utils.UInt64ToBytesSafepos(v, m_tmp, 0);
+ AddBytes(m_tmp, 8);
+ }
+ }
+
+ public void AddVector3(Vector3 v)
+ {
+ if (v == Vector3.Zero)
+ AddZeros(12);
+ else
+ {
+ v.ToBytes(m_tmp, 0);
+ AddBytes(m_tmp, 12);
+ }
+ }
+
+ public void AddVector4(Vector4 v)
+ {
+ if (v == Vector4.Zero)
+ AddZeros(16);
+ else
+ {
+ v.ToBytes(m_tmp, 0);
+ AddBytes(m_tmp, 16);
+ }
+ }
+
+ public void AddNormQuat(Quaternion v)
+ {
+ v.ToBytes(m_tmp, 0);
+ AddBytes(m_tmp, 12);
+ }
+
+ public void AddUUID(UUID v)
+ {
+ v.ToBytes(m_tmp, 0);
+ AddBytes(m_tmp, 16);
+ }
+ }
+}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f362b06f0a..49aca3c18e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Threading;
@@ -57,15 +58,9 @@ namespace OpenMetaverse
/// UDP socket, used in either client or server mode
private Socket m_udpSocket;
- ///
- /// Are we to use object pool(s) to reduce memory churn when receiving data?
- ///
- public bool UsePools { get; protected set; }
-
- ///
- /// Pool to use for handling data. May be null if UsePools = false;
- ///
- protected OpenSim.Framework.Pool Pool { get; private set; }
+ public static Object m_udpBuffersPoolLock = new Object();
+ public static UDPPacketBuffer[] m_udpBuffersPool = new UDPPacketBuffer[1000];
+ public static int m_udpBuffersPoolPtr = -1;
/// Returns true if the server is currently listening for inbound packets, otherwise false
public bool IsRunningInbound { get; private set; }
@@ -186,6 +181,37 @@ namespace OpenMetaverse
if(m_udpSocket !=null)
try { m_udpSocket.Close(); } catch { }
}
+
+ public UDPPacketBuffer GetNewUDPBuffer(IPEndPoint remoteEndpoint)
+ {
+ lock (m_udpBuffersPoolLock)
+ {
+ if (m_udpBuffersPoolPtr >= 0)
+ {
+ UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr];
+ m_udpBuffersPool[m_udpBuffersPoolPtr] = null;
+ m_udpBuffersPoolPtr--;
+ buf.RemoteEndPoint = remoteEndpoint;
+ return buf;
+ }
+ }
+ return new UDPPacketBuffer(remoteEndpoint);
+ }
+
+ public void FreeUDPBuffer(UDPPacketBuffer buf)
+ {
+ lock (m_udpBuffersPoolLock)
+ {
+ if (m_udpBuffersPoolPtr < 999)
+ {
+ buf.RemoteEndPoint = null;
+ buf.DataLength = 0;
+ m_udpBuffersPoolPtr++;
+ m_udpBuffersPool[m_udpBuffersPoolPtr] = buf;
+ }
+ }
+ }
+
///
/// Start inbound UDP packet handling.
///
@@ -202,6 +228,7 @@ namespace OpenMetaverse
/// manner (not throwing an exception when the remote side resets the
/// connection). This call is ignored on Mono where the flag is not
/// necessary
+
public virtual void StartInbound(int recvBufferSize)
{
if (!IsRunningInbound)
@@ -306,101 +333,55 @@ namespace OpenMetaverse
IsRunningOutbound = false;
}
- public virtual bool EnablePools()
- {
- if (!UsePools)
- {
- Pool = new Pool(() => new UDPPacketBuffer(), 500);
-
- UsePools = true;
-
- return true;
- }
-
- return false;
- }
-
- public virtual bool DisablePools()
- {
- if (UsePools)
- {
- UsePools = false;
-
- // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
-
- return true;
- }
-
- return false;
- }
-
private void AsyncBeginReceive()
{
- UDPPacketBuffer buf;
+ if (!IsRunningInbound)
+ return;
- // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other
- // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux.
- // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads. Requires more investigation.
-// if (UsePools)
-// buf = Pool.GetObject();
-// else
- buf = new UDPPacketBuffer();
-
- if (IsRunningInbound)
+ UDPPacketBuffer buf = GetNewUDPBuffer(new IPEndPoint(IPAddress.Any, 0)); // we need a fresh one here, for now at least
+ try
{
- try
+ // kick off an async read
+ m_udpSocket.BeginReceiveFrom(
+ buf.Data,
+ 0,
+ buf.Data.Length,
+ SocketFlags.None,
+ ref buf.RemoteEndPoint,
+ AsyncEndReceive,
+ buf);
+ }
+ catch (SocketException e)
+ {
+ if (e.SocketErrorCode == SocketError.ConnectionReset)
{
- // kick off an async read
- m_udpSocket.BeginReceiveFrom(
- //wrappedBuffer.Instance.Data,
- buf.Data,
- 0,
- UDPPacketBuffer.BUFFER_SIZE,
- SocketFlags.None,
- ref buf.RemoteEndPoint,
- AsyncEndReceive,
- //wrappedBuffer);
- buf);
- }
- catch (SocketException e)
- {
- if (e.SocketErrorCode == SocketError.ConnectionReset)
+ m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
+ bool salvaged = false;
+ while (!salvaged)
{
- m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
- bool salvaged = false;
- while (!salvaged)
+ try
{
- try
- {
- m_udpSocket.BeginReceiveFrom(
- //wrappedBuffer.Instance.Data,
- buf.Data,
- 0,
- UDPPacketBuffer.BUFFER_SIZE,
- SocketFlags.None,
- ref buf.RemoteEndPoint,
- AsyncEndReceive,
- //wrappedBuffer);
- buf);
- salvaged = true;
- }
- catch (SocketException) { }
- catch (ObjectDisposedException) { return; }
+ m_udpSocket.BeginReceiveFrom(
+ buf.Data,
+ 0,
+ buf.Data.Length,
+ SocketFlags.None,
+ ref buf.RemoteEndPoint,
+ AsyncEndReceive,
+ buf);
+ salvaged = true;
}
-
- m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
+ catch (SocketException) { }
+ catch (ObjectDisposedException) { return; }
}
+
+ m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
}
- catch (ObjectDisposedException e)
- {
- m_log.Error(
- string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
- }
- catch (Exception e)
- {
- m_log.Error(
- string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
- }
+ }
+ catch (Exception e)
+ {
+ m_log.Error(
+ string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
}
}
@@ -453,11 +434,6 @@ namespace OpenMetaverse
UdpReceives, se.ErrorCode),
se);
}
- catch (ObjectDisposedException e)
- {
- m_log.Error(
- string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
- }
catch (Exception e)
{
m_log.Error(
@@ -465,14 +441,12 @@ namespace OpenMetaverse
}
finally
{
-// if (UsePools)
-// Pool.ReturnObject(buffer);
-
AsyncBeginReceive();
}
}
}
+/* not in use
public void AsyncBeginSend(UDPPacketBuffer buf)
{
// if (IsRunningOutbound)
@@ -511,9 +485,11 @@ namespace OpenMetaverse
catch (SocketException) { }
catch (ObjectDisposedException) { }
}
-
+*/
public void SyncSend(UDPPacketBuffer buf)
{
+ if(buf.RemoteEndPoint == null)
+ return; // already expired
try
{
m_udpSocket.SendTo(
@@ -527,7 +503,7 @@ namespace OpenMetaverse
}
catch (SocketException e)
{
- m_log.Warn("[UDPBASE]: sync send SocketException {0} " + e.Message);
+ m_log.WarnFormat("[UDPBASE]: sync send SocketException {0} {1}", buf.RemoteEndPoint, e.Message);
}
catch (ObjectDisposedException) { }
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index f8ec97ae83..3277638697 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -66,9 +66,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public Int64 MinimumAdaptiveThrottleRate;
- /// Amount of the texture throttle to steal for the task throttle
- public double CannibalizeTextureRate;
-
public int ClientMaxRate;
public float BrustTime;
@@ -104,12 +101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
AdaptiveThrottlesEnabled = false;
MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000);
-
- // http textures do use udp bandwidth setting
-// CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
-// CannibalizeTextureRate = Util.Clamp(CannibalizeTextureRate,0.0, 0.9);
- CannibalizeTextureRate = 0f;
-
}
catch (Exception) { }
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
index 76f4c6f86e..1f978e13c3 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
@@ -189,8 +189,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Process all the pending adds
OutgoingPacket pendingAdd;
while (m_pendingAdds.TryDequeue(out pendingAdd))
+ {
if (pendingAdd != null)
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
+ }
// Process all the pending removes, including updating statistics and round-trip times
PendingAck pendingAcknowledgement;
@@ -204,13 +206,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
m_packets.Remove(pendingAcknowledgement.SequenceNumber);
+ // Update stats
+ Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
+
+ ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer);
+ ackedPacket.Buffer = null;
+
// As with other network applications, assume that an acknowledged packet is an
// indication that the network can handle a little more load, speed up the transmission
ackedPacket.Client.FlowThrottle.AcknowledgePackets(1);
- // Update stats
- Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
-
if (!pendingAcknowledgement.FromResend)
{
// Calculate the round-trip time for this packet and its ACK
@@ -244,6 +249,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Update stats
Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
+
+ removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer);
+ removedPacket.Buffer = null;
}
}
}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index d36d770152..5205576246 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -953,13 +953,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return;
}
- // Saving attachments for NPCs messes them up for the real owner!
- INPCModule module = m_scene.RequestModuleInterface();
- if (module != null)
- {
- if (module.IsNPC(sp.UUID, m_scene))
- return;
- }
+ if(sp.IsNPC)
+ return;
if (grp.HasGroupChanged)
{
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index 4e1958a9c4..10bc6aa188 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -77,7 +77,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
}
scene.EventManager.OnAvatarKilled += KillAvatar;
- scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
}
public void RemoveRegion(Scene scene)
@@ -86,7 +85,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
m_scenel.Remove(scene.RegionInfo.RegionHandle);
scene.EventManager.OnAvatarKilled -= KillAvatar;
- scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
}
public void RegionLoaded(Scene scene)
@@ -177,31 +175,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
deadAvatar.setHealthWithUpdate(100.0f);
deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient);
}
-
- private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
- {
- try
- {
- ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
- if (obj == null)
- return;
- if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
- || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
- {
- avatar.Invulnerable = false;
- }
- else
- {
- avatar.Invulnerable = true;
- if (avatar.Health < 100.0f)
- {
- avatar.setHealthWithUpdate(100.0f);
- }
- }
- }
- catch (Exception)
- {
- }
- }
}
}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index d6c65a1e3f..69c1e4edce 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -526,16 +526,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
item.AssetType = (int)AssetType.Object;
item.AssetID = asset.FullID;
- if (DeRezAction.SaveToExistingUserInventoryItem == action)
+ if (action == DeRezAction.SaveToExistingUserInventoryItem)
{
m_Scene.InventoryService.UpdateItem(item);
}
else
{
- AddPermissions(item, objlist[0], objlist, remoteClient);
+ bool isowner = remoteClient != null && item.Owner == remoteClient.AgentId;
+ if(action == DeRezAction.Return)
+ AddPermissions(item, objlist[0], objlist, null);
+ else if(action == DeRezAction.Delete && !isowner)
+ AddPermissions(item, objlist[0], objlist, null);
+ else
+ AddPermissions(item, objlist[0], objlist, remoteClient);
+
m_Scene.AddInventoryItem(item);
- if (remoteClient != null && item.Owner == remoteClient.AgentId)
+ if (isowner)
{
remoteClient.SendInventoryItemCreateUpdate(item, 0);
}
@@ -1010,7 +1017,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
rootPart.ParentGroup.ResumeScripts();
- group.ScheduleGroupForFullUpdate();
+ group.ScheduleGroupForFullAnimUpdate();
}
else
m_Scene.AddNewSceneObject(group, true, false);
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index c3f6d6b2df..83d91c40b5 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Concurrent;
using System.IO;
using System.Net;
using System.Net.Mail;
@@ -94,18 +95,31 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private object HttpListLock = new object();
- private int httpTimeout = 30000;
+ private object m_httpListLock = new object();
+ private int m_httpTimeout = 30000;
private string m_name = "HttpScriptRequests";
private OutboundUrlFilter m_outboundUrlFilter;
private string m_proxyurl = "";
private string m_proxyexcepts = "";
+ private float m_primPerSec = 1.0f;
+ private float m_primBurst = 3.0f;
+ private float m_primOwnerPerSec = 25.0f;
+ private float m_primOwnerBurst = 5.0f;
+
+ private struct ThrottleData
+ {
+ public double lastTime;
+ public float count;
+ }
+
//
private Dictionary m_pendingRequests;
- private Scene m_scene;
- // private Queue rpcQueue = new Queue();
+ private ConcurrentQueue m_CompletedRequests;
+ private ConcurrentDictionary m_RequestsThrottle;
+ private ConcurrentDictionary m_OwnerRequestsThrottle;
+
public static SmartThreadPool ThreadPool = null;
public HttpRequestModule()
@@ -119,10 +133,77 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
return UUID.Zero;
}
+ public bool CheckThrottle(uint localID, UUID ownerID)
+ {
+ ThrottleData th;
+ double now = Util.GetTimeStamp();
+ bool ret;
+
+ if (m_RequestsThrottle.TryGetValue(localID, out th))
+ {
+ double delta = now - th.lastTime;
+ th.lastTime = now;
+
+ float add = (float)(m_primPerSec * delta);
+ th.count += add;
+ if (th.count > m_primBurst)
+ th.count = m_primBurst;
+
+ ret = th.count > 0;
+ if (ret)
+ th.count--;
+ }
+ else
+ {
+ th = new ThrottleData()
+ {
+ lastTime = now,
+ count = m_primBurst - 1
+ };
+ ret = true;
+ }
+ m_RequestsThrottle[localID] = th;
+
+ if(!ret)
+ return false;
+
+ if (m_OwnerRequestsThrottle.TryGetValue(ownerID, out th))
+ {
+ double delta = now - th.lastTime;
+ th.lastTime = now;
+
+ float add = (float)(m_primOwnerPerSec * delta);
+ th.count += add;
+ if (th.count > m_primOwnerBurst)
+ th.count = m_primOwnerBurst;
+
+ ret = th.count > 0;
+ if (ret)
+ th.count--;
+ }
+ else
+ {
+ th = new ThrottleData()
+ {
+ lastTime = now,
+ count = m_primOwnerBurst - 1
+ };
+ }
+ m_OwnerRequestsThrottle[ownerID] = th;
+
+ return ret;
+ }
+
public UUID StartHttpRequest(
uint localID, UUID itemID, string url, List parameters, Dictionary headers, string body,
out HttpInitialRequestStatus status)
{
+ if (!CheckAllowed(new Uri(url)))
+ {
+ status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER;
+ return UUID.Zero;
+ }
+
UUID reqID = UUID.Random();
HttpRequestClass htc = new HttpRequestClass();
@@ -207,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
htc.ItemID = itemID;
htc.Url = url;
htc.ReqID = reqID;
- htc.HttpTimeout = httpTimeout;
+ htc.HttpTimeout = m_httpTimeout;
htc.OutboundBody = body;
htc.ResponseHeaders = headers;
htc.proxyurl = m_proxyurl;
@@ -216,16 +297,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
// Same number as default HttpWebRequest.MaximumAutomaticRedirections
htc.MaxRedirects = 50;
- if (StartHttpRequest(htc))
- {
- status = HttpInitialRequestStatus.OK;
- return htc.ReqID;
- }
- else
- {
- status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER;
- return UUID.Zero;
- }
+ lock (m_httpListLock)
+ m_pendingRequests.Add(reqID, htc);
+
+ htc.Process();
+ status = HttpInitialRequestStatus.OK;
+ return reqID;
}
///
@@ -237,34 +314,21 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
return m_outboundUrlFilter.CheckAllowed(url);
}
- public bool StartHttpRequest(HttpRequestClass req)
- {
- if (!CheckAllowed(new Uri(req.Url)))
- return false;
-
- lock (HttpListLock)
- {
- m_pendingRequests.Add(req.ReqID, req);
- }
-
- req.Process();
-
- return true;
- }
-
public void StopHttpRequest(uint m_localID, UUID m_itemID)
{
- if (m_pendingRequests != null)
+ List toremove = new List();
+ lock (m_httpListLock)
{
- lock (HttpListLock)
+ foreach (HttpRequestClass tmpReq in m_pendingRequests.Values)
{
- HttpRequestClass tmpReq;
- if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
+ if(tmpReq.ItemID == m_itemID)
{
tmpReq.Stop();
- m_pendingRequests.Remove(m_itemID);
+ toremove.Add(tmpReq.ReqID);
}
}
+ foreach(UUID id in toremove)
+ m_pendingRequests.Remove(id);
}
}
@@ -276,37 +340,35 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
* finished. I thought about setting up a queue for this, but
* it will need some refactoring and this works 'enough' right now
*/
+ public void GotCompletedRequest(HttpRequestClass req)
+ {
+ lock (m_httpListLock)
+ {
+ if (req.Removed)
+ return;
+ m_pendingRequests.Remove(req.ReqID);
+ m_CompletedRequests.Enqueue(req);
+ }
+ }
public IServiceRequest GetNextCompletedRequest()
{
- lock (HttpListLock)
- {
- foreach (UUID luid in m_pendingRequests.Keys)
- {
- HttpRequestClass tmpReq;
+ HttpRequestClass req;
+ if(m_CompletedRequests.TryDequeue(out req))
+ return req;
- if (m_pendingRequests.TryGetValue(luid, out tmpReq))
- {
- if (tmpReq.Finished)
- {
- return tmpReq;
- }
- }
- }
- }
return null;
}
- public void RemoveCompletedRequest(UUID id)
+ public void RemoveCompletedRequest(UUID reqId)
{
- lock (HttpListLock)
+ lock (m_httpListLock)
{
HttpRequestClass tmpReq;
- if (m_pendingRequests.TryGetValue(id, out tmpReq))
+ if (m_pendingRequests.TryGetValue(reqId, out tmpReq))
{
tmpReq.Stop();
- tmpReq = null;
- m_pendingRequests.Remove(id);
+ m_pendingRequests.Remove(reqId);
}
}
}
@@ -322,17 +384,28 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384);
-
m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
- int maxThreads = 15;
- IConfig httpConfig = config.Configs["HttpRequestModule"];
+ int maxThreads = 8;
+ IConfig httpConfig = config.Configs["ScriptsHttpRequestModule"];
if (httpConfig != null)
{
maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
+ m_primBurst = httpConfig.GetFloat("PrimRequestsBurst", m_primBurst);
+ m_primPerSec = httpConfig.GetFloat("PrimRequestsPerSec", m_primPerSec);
+ m_primOwnerBurst = httpConfig.GetFloat("PrimOwnerRequestsBurst", m_primOwnerBurst);
+ m_primOwnerPerSec = httpConfig.GetFloat("PrimOwnerRequestsPerSec", m_primOwnerPerSec);
+ m_httpTimeout = httpConfig.GetInt("RequestsTimeOut", m_httpTimeout);
+ if(m_httpTimeout > 60000)
+ m_httpTimeout = 60000;
+ else if(m_httpTimeout < 200)
+ m_httpTimeout = 200;
}
m_pendingRequests = new Dictionary();
+ m_CompletedRequests = new ConcurrentQueue();
+ m_RequestsThrottle = new ConcurrentDictionary();
+ m_OwnerRequestsThrottle = new ConcurrentDictionary();
// First instance sets this up for all sims
if (ThreadPool == null)
@@ -352,16 +425,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public void AddRegion(Scene scene)
{
- m_scene = scene;
-
- m_scene.RegisterModuleInterface(this);
+ scene.RegisterModuleInterface(this);
}
public void RemoveRegion(Scene scene)
{
scene.UnregisterModuleInterface(this);
- if (scene == m_scene)
- m_scene = null;
}
public void PostInitialise()
@@ -406,11 +475,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
///
public HttpRequestModule RequestModule { get; set; }
- private bool _finished;
- public bool Finished
- {
- get { return _finished; }
- }
+ public bool Finished { get; private set;}
+ public bool Removed{ get; set;}
public static int HttpBodyMaxLenMAX = 16384;
@@ -427,19 +493,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public bool HttpPragmaNoCache = true;
// Request info
- private UUID _itemID;
- public UUID ItemID
- {
- get { return _itemID; }
- set { _itemID = value; }
- }
- private uint _localID;
- public uint LocalID
- {
- get { return _localID; }
- set { _localID = value; }
- }
- public DateTime Next;
+ public UUID ReqID { get; set; }
+ public UUID ItemID { get; set;}
+ public uint LocalID { get; set;}
+
public string proxyurl;
public string proxyexcepts;
@@ -454,12 +511,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public int MaxRedirects { get; set; }
public string OutboundBody;
- private UUID _reqID;
- public UUID ReqID
- {
- get { return _reqID; }
- set { _reqID = value; }
- }
+
public HttpWebRequest Request;
public string ResponseBody;
public List ResponseMetadata;
@@ -469,10 +521,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public void Process()
{
- _finished = false;
-
- lock (HttpRequestModule.ThreadPool)
- WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
+ WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
}
private object StpSendWrapper(object o)
@@ -521,6 +570,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public void SendRequest()
{
+ if(Removed)
+ return;
+
HttpWebResponse response = null;
Stream resStream = null;
byte[] buf = new byte[HttpBodyMaxLenMAX + 16];
@@ -534,6 +586,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
Request.AllowAutoRedirect = false;
Request.KeepAlive = false;
+ Request.Timeout = HttpTimeout;
//This works around some buggy HTTP Servers like Lighttpd
Request.ServicePoint.Expect100Continue = false;
@@ -593,7 +646,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
bstream.Write(data, 0, data.Length);
}
- Request.Timeout = HttpTimeout;
try
{
// execute the request
@@ -672,7 +724,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
if (response != null)
response.Close();
-
// We need to resubmit
if (
(Status == (int)HttpStatusCode.MovedPermanently
@@ -684,7 +735,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{
Status = (int)OSHttpStatusCode.ClientErrorJoker;
ResponseBody = "Number of redirects exceeded max redirects";
- _finished = true;
+ WorkItem = null;
+ RequestModule.GotCompletedRequest(this);
}
else
{
@@ -694,13 +746,15 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{
Status = (int)OSHttpStatusCode.ClientErrorJoker;
ResponseBody = "HTTP redirect code but no location header";
- _finished = true;
+ WorkItem = null;
+ RequestModule.GotCompletedRequest(this);
}
else if (!RequestModule.CheckAllowed(new Uri(location)))
{
Status = (int)OSHttpStatusCode.ClientErrorJoker;
ResponseBody = "URL from HTTP redirect blocked: " + location;
- _finished = true;
+ WorkItem = null;
+ RequestModule.GotCompletedRequest(this);
}
else
{
@@ -717,9 +771,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
}
else
{
- _finished = true;
+ WorkItem = null;
if (ResponseBody == null)
ResponseBody = String.Empty;
+ RequestModule.GotCompletedRequest(this);
}
}
}
@@ -728,10 +783,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{
try
{
+ Removed = true;
+ if(WorkItem == null)
+ return;
+
if (!WorkItem.Cancel())
- {
WorkItem.Cancel(true);
- }
}
catch (Exception)
{
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 2e801e35b4..ac28ceeac0 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -1204,28 +1204,33 @@ namespace OpenSim.Region.CoreModules.World.Estate
}
}
- private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey)
+ private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey, bool kick)
{
+ if (prey == UUID.Zero)
+ return;
+
EstateTeleportOneUserHomeRequest evOverride = OnEstateTeleportOneUserHomeRequest;
if(evOverride != null)
{
- evOverride(remover_client, invoice, senderID, prey);
+ evOverride(remover_client, invoice, senderID, prey, kick);
return;
}
if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false))
return;
- if (prey != UUID.Zero)
+ ScenePresence s = Scene.GetScenePresence(prey);
+ if (s != null && !s.IsDeleted && !s.IsInTransit)
{
- ScenePresence s = Scene.GetScenePresence(prey);
- if (s != null && !s.IsDeleted && !s.IsInTransit)
+ if (kick)
{
- if (!Scene.TeleportClientHome(prey, s.ControllingClient))
- {
- s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
- Scene.CloseAgent(s.UUID, false);
- }
+ s.ControllingClient.Kick("You have been kicked");
+ Scene.CloseAgent(s.UUID, false);
+ }
+ else if (!Scene.TeleportClientHome(prey, s.ControllingClient))
+ {
+ s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed ");
+ Scene.CloseAgent(s.UUID, false);
}
}
}
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
index f4a174a7a7..c8b9032c36 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
@@ -204,7 +204,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message);
}
- private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey)
+ private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey, bool kick)
{
if (prey == UUID.Zero)
return;
@@ -227,8 +227,20 @@ namespace OpenSim.Region.CoreModules.World.Estate
ScenePresence p = scene.GetScenePresence(prey);
if (p != null && !p.IsChildAgent && !p.IsDeleted && !p.IsInTransit)
{
- p.ControllingClient.SendTeleportStart(16);
- scene.TeleportClientHome(prey, client);
+ if (kick)
+ {
+ p.ControllingClient.Kick("You have been kicked out");
+ s.CloseAgent(p.UUID, false);
+ }
+ else
+ {
+ p.ControllingClient.SendTeleportStart(16);
+ if (!s.TeleportClientHome(prey, client))
+ {
+ p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed");
+ s.CloseAgent(p.UUID, false);
+ }
+ }
return;
}
}
@@ -259,6 +271,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
{
p.ControllingClient.SendTeleportStart(16);
scene.TeleportClientHome(p.ControllingClient.AgentId, client);
+ if (!s.TeleportClientHome(p.ControllingClient.AgentId, client))
+ {
+ p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
+ s.CloseAgent(p.UUID, false);
+ }
}
});
}
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index 978c248610..2c75844fea 100644
--- a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
+++ b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
@@ -87,5 +87,6 @@ namespace OpenSim.Region.Framework.Interfaces
void StopHttpRequest(uint m_localID, UUID m_itemID);
IServiceRequest GetNextCompletedRequest();
void RemoveCompletedRequest(UUID id);
+ bool CheckThrottle(uint localID, UUID onerID);
}
}
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 7509686bbb..eae6d6f44c 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -94,19 +94,15 @@ namespace OpenSim.Region.Framework.Scenes
m_inventoryDeletes.Enqueue(dtis);
}
- if (Enabled)
- lock (m_inventoryTicker)
- m_inventoryTicker.Start();
-
- // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object
- // has gone to inventory, it will reappear in the region again on restart instead of being lost.
- // This is not ideal since the object will still be available for manipulation when it should be, but it's
- // better than losing the object for now.
if (permissionToDelete)
{
foreach (SceneObjectGroup g in objectGroups)
g.DeleteGroupFromScene(false);
}
+
+ if (Enabled)
+ lock (m_inventoryTicker)
+ m_inventoryTicker.Start();
}
private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index f76f8828d0..edc8886fbf 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -539,7 +539,7 @@ namespace OpenSim.Region.Framework.Scenes
///
///
public event ScriptChangedEvent OnScriptChangedEvent;
- public delegate void ScriptChangedEvent(uint localID, uint change);
+ public delegate void ScriptChangedEvent(uint localID, uint change, object data);
public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed);
@@ -1185,7 +1185,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- public void TriggerOnScriptChangedEvent(uint localID, uint change)
+ public void TriggerOnScriptChangedEvent(uint localID, uint change, object parameter = null)
{
ScriptChangedEvent handlerScriptChangedEvent = OnScriptChangedEvent;
if (handlerScriptChangedEvent != null)
@@ -1194,7 +1194,7 @@ namespace OpenSim.Region.Framework.Scenes
{
try
{
- d(localID, change);
+ d(localID, change, parameter);
}
catch (Exception e)
{
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index e6e035402f..debcad373d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -2110,7 +2110,7 @@ namespace OpenSim.Region.Framework.Scenes
// build a list of eligible objects
List deleteIDs = new List();
List deleteGroups = new List();
- List takeGroups = new List();
+ List takeCopyGroups = new List();
List takeDeleteGroups = new List();
ScenePresence sp = null;
@@ -2119,11 +2119,10 @@ namespace OpenSim.Region.Framework.Scenes
else if(action != DeRezAction.Return)
return; // only Return can be called without a client
- // Start with true for both, then remove the flags if objects
- // that we can't derez are part of the selection
- bool permissionToTake = true;
- bool permissionToTakeCopy = true;
- bool permissionToDelete = true;
+ // this is not as 0.8x code
+ // 0.8x did refuse all operation is not allowed on all objects
+ // this will do it on allowed objects
+ // current viewers only ask if all allowed
foreach (uint localID in localIDs)
{
@@ -2136,8 +2135,8 @@ namespace OpenSim.Region.Framework.Scenes
continue;
}
- // Already deleted by someone else
- if (part.ParentGroup.IsDeleted)
+ SceneObjectGroup grp = part.ParentGroup;
+ if (grp == null || grp.IsDeleted)
{
//Client still thinks the object exists, kill it
deleteIDs.Add(localID);
@@ -2145,132 +2144,105 @@ namespace OpenSim.Region.Framework.Scenes
}
// Can't delete child prims
- if (part != part.ParentGroup.RootPart)
+ if (part != grp.RootPart)
continue;
- SceneObjectGroup grp = part.ParentGroup;
if (grp.IsAttachment)
- continue;
+ {
+ if(!sp.IsGod || action != DeRezAction.Return || action != DeRezAction.Delete)
+ continue;
+ // this may break the attachment, but its a security action
+ // viewers don't allow it anyways
+ }
// If child prims have invalid perms, fix them
grp.AdjustChildPrimPermissions(false);
- if (remoteClient == null)
+ switch (action)
{
- // Autoreturn has a null client. Nothing else does. So
- // allow only returns
- if (action != DeRezAction.Return)
+ case DeRezAction.SaveToExistingUserInventoryItem:
{
- m_log.WarnFormat(
- "[AGENT INVENTORY]: Ignoring attempt to {0} {1} {2} without a client",
- action, grp.Name, grp.UUID);
- return;
+ if (Permissions.CanTakeCopyObject(grp, sp))
+ takeCopyGroups.Add(grp);
+ break;
}
- permissionToTakeCopy = false;
- }
- else
- {
- if (action == DeRezAction.TakeCopy)
+ case DeRezAction.TakeCopy:
{
- if (!Permissions.CanTakeCopyObject(grp, sp))
- permissionToTakeCopy = false;
- }
- else
- {
- permissionToTakeCopy = false;
- }
- if (!Permissions.CanTakeObject(grp, sp))
- permissionToTake = false;
-
- if (!Permissions.CanDeleteObject(grp, remoteClient))
- permissionToDelete = false;
- }
-
- // Handle god perms
- if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
- {
- permissionToTake = true;
- permissionToTakeCopy = true;
- permissionToDelete = true;
- }
-
- // If we're re-saving, we don't even want to delete
- if (action == DeRezAction.SaveToExistingUserInventoryItem)
- permissionToDelete = false;
-
- // if we want to take a copy, we also don't want to delete
- // Note: after this point, the permissionToTakeCopy flag
- // becomes irrelevant. It already includes the permissionToTake
- // permission and after excluding no copy items here, we can
- // just use that.
- if (action == DeRezAction.TakeCopy)
- {
- // If we don't have permission, stop right here
- if (!permissionToTakeCopy)
- {
- remoteClient.SendAlertMessage("You don't have permission to take the object");
- return;
+ if (Permissions.CanTakeCopyObject(grp, sp))
+ takeCopyGroups.Add(grp);
+ break;
}
- permissionToTake = true;
- // Don't delete
- permissionToDelete = false;
- }
-
- if (action == DeRezAction.Return)
- {
- if (remoteClient != null)
+ case DeRezAction.Take:
{
- if (Permissions.CanReturnObjects(
- null,
- remoteClient,
- new List() {grp}))
+ if (Permissions.CanTakeObject(grp, sp))
+ takeDeleteGroups.Add(grp);
+ break;
+ }
+
+ case DeRezAction.GodTakeCopy:
+ {
+ if((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
+ takeCopyGroups.Add(grp);
+ break;
+ }
+
+ case DeRezAction.Delete:
+ {
+ if (Permissions.CanDeleteObject(grp, remoteClient))
{
- permissionToTake = true;
- permissionToDelete = true;
- if(AddToReturns)
- AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition,
- "parcel owner return");
+ if(m_useTrashOnDelete || (sp.IsGod && grp.OwnerID != sp.UUID))
+ takeDeleteGroups.Add(grp);
+ else
+ deleteGroups.Add(grp);
}
+ break;
}
- else // Auto return passes through here with null agent
- {
- permissionToTake = true;
- permissionToDelete = true;
- }
- }
- if (permissionToDelete)
- {
- if (permissionToTake)
- takeDeleteGroups.Add(grp);
- else
- deleteGroups.Add(grp);
- deleteIDs.Add(grp.LocalId);
+ case DeRezAction.Return:
+ {
+ if (remoteClient != null)
+ {
+ if (Permissions.CanReturnObjects( null, remoteClient, new List() {grp}))
+ {
+ takeDeleteGroups.Add(grp);
+ if (AddToReturns)
+ AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition,
+ "parcel owner return");
+ }
+ }
+ else // Auto return passes through here with null agent
+ {
+ takeDeleteGroups.Add(grp);
+ }
+ break;
+ }
+
+ default:
+ break;
}
- else if(permissionToTake)
- takeGroups.Add(grp);
}
- SendKillObject(deleteIDs);
+ if(deleteIDs.Count > 0)
+ SendKillObject(deleteIDs);
if (takeDeleteGroups.Count > 0)
{
- m_asyncSceneObjectDeleter.DeleteToInventory(
- action, destinationID, takeDeleteGroups, remoteClient,
- true);
+ m_asyncSceneObjectDeleter.DeleteToInventory(action, destinationID, takeDeleteGroups,
+ remoteClient, true);
}
- if (takeGroups.Count > 0)
+
+ if (takeCopyGroups.Count > 0)
{
- m_asyncSceneObjectDeleter.DeleteToInventory(
- action, destinationID, takeGroups, remoteClient,
- false);
+ m_asyncSceneObjectDeleter.DeleteToInventory(action, destinationID, takeCopyGroups,
+ remoteClient, false);
}
+
if (deleteGroups.Count > 0)
{
foreach (SceneObjectGroup g in deleteGroups)
- DeleteSceneObject(g, true);
+ DeleteSceneObject(g, false);
}
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index b526fe936b..ea037beb30 100755
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1913,9 +1913,8 @@ namespace OpenSim.Region.Framework.Scenes
{
if (parentGroup.OwnerID == child.OwnerID)
{
- parentGroup.LinkToGroup(child);
-
child.DetachFromBackup();
+ parentGroup.LinkToGroup(child);
// this is here so physics gets updated!
// Don't remove! Bad juju! Stay away! or fix physics!
@@ -1943,7 +1942,6 @@ namespace OpenSim.Region.Framework.Scenes
*/
parentGroup.AdjustChildPrimPermissions(false);
parentGroup.HasGroupChanged = true;
- parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
parentGroup.ScheduleGroupForFullAnimUpdate();
Monitor.Exit(m_linkLock);
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index bf217a5f3c..8899e96dba 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -154,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
// We're adding this to a prim we don't own. Force
// owner change
taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
-
+ taskItem.LastOwnerID = item.Owner;
}
else
{
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index a23ebbfa46..312ce26e4a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -3242,8 +3242,6 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup.Scene.GetNumberOfClients() == 0)
return;
- ParentGroup.QueueForUpdateCheck();
-
bool isfull = false;
if (ParentGroup.IsAttachment)
{
@@ -3254,6 +3252,8 @@ namespace OpenSim.Region.Framework.Scenes
lock (UpdateFlagLock)
UpdateFlag |= update;
+ ParentGroup.QueueForUpdateCheck();
+
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull);
}
@@ -4439,10 +4439,10 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectSerializer.SOPToXml2(xmlWriter, this, new Dictionary());
}
- public void TriggerScriptChangedEvent(Changed val)
+ public void TriggerScriptChangedEvent(Changed val, object data = null)
{
if (ParentGroup != null && ParentGroup.Scene != null)
- ParentGroup.Scene.EventManager.TriggerOnScriptChangedEvent(LocalId, (uint)val);
+ ParentGroup.Scene.EventManager.TriggerOnScriptChangedEvent(LocalId, (uint)val, data);
}
public void TrimPermissions()
@@ -5130,11 +5130,10 @@ namespace OpenSim.Region.Framework.Scenes
if (changeFlags == 0)
return;
- m_shape.TextureEntry = newTex.GetBytes();
+ m_shape.TextureEntry = newTex.GetBytes(9);
TriggerScriptChangedEvent(changeFlags);
ParentGroup.HasGroupChanged = true;
- ScheduleFullUpdate();
-
+ ScheduleUpdate(PrimUpdateFlags.Textures);
}
///
@@ -5160,10 +5159,10 @@ namespace OpenSim.Region.Framework.Scenes
if (changeFlags == 0)
return;
- m_shape.TextureEntry = newTex.GetBytes();
+ m_shape.TextureEntry = newTex.GetBytes(9);
TriggerScriptChangedEvent(changeFlags);
ParentGroup.HasGroupChanged = true;
- ScheduleFullUpdate();
+ ScheduleUpdate(PrimUpdateFlags.Textures);
}
internal void UpdatePhysicsSubscribedEvents()
@@ -5575,20 +5574,26 @@ namespace OpenSim.Region.Framework.Scenes
// handle osVolumeDetect
public void ScriptSetVolumeDetect(bool makeVolumeDetect)
{
+ if(ParentGroup.IsDeleted)
+ return;
+
if(_parentID == 0)
{
- // if root prim do it via SOG
+ // if root prim do it is like llVolumeDetect
ParentGroup.ScriptSetVolumeDetect(makeVolumeDetect);
return;
}
- bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
- bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
- bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
+ if(ParentGroup.IsVolumeDetect)
+ return; // entire linkset is phantom already
+
+ bool wasUsingPhysics = ParentGroup.UsesPhysics;
+ bool wasTemporary = ParentGroup.IsTemporary;
+ bool wasPhantom = ParentGroup.IsPhantom;
if(PhysActor != null)
PhysActor.Building = true;
- UpdatePrimFlags(wasUsingPhysics,wasTemporary,wasPhantom,makeVolumeDetect,false);
+ UpdatePrimFlags(wasUsingPhysics, wasTemporary, wasPhantom, makeVolumeDetect, false);
}
protected static int m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0x5fffafL);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 4934b8327c..a0f895933f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -815,10 +815,10 @@ namespace OpenSim.Region.Framework.Scenes
m_items.LockItemsForWrite(true);
m_items.Add(item.ItemID, item);
m_items.LockItemsForWrite(false);
- if (allowedDrop)
- m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
- else
- m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
+ if (allowedDrop)
+ m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP, item.ItemID);
+ else
+ m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
m_part.AggregateInnerPerms();
m_inventorySerial++;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cfb1be4f98..1c5d23d9b4 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -507,7 +507,19 @@ namespace OpenSim.Region.Framework.Scenes
///
/// Physical scene representation of this Avatar.
///
- public PhysicsActor PhysicsActor { get; private set; }
+
+ PhysicsActor m_physActor;
+ public PhysicsActor PhysicsActor
+ {
+ get
+ {
+ return m_physActor;
+ }
+ private set
+ {
+ m_physActor = value;
+ }
+ }
///
/// Record user movement inputs.
@@ -523,7 +535,12 @@ namespace OpenSim.Region.Framework.Scenes
public bool Invulnerable
{
- set { m_invulnerable = value; }
+ set
+ {
+ m_invulnerable = value;
+ if(value && Health != 100.0f)
+ Health = 100.0f;
+ }
get { return m_invulnerable; }
}
@@ -1636,15 +1653,15 @@ namespace OpenSim.Region.Framework.Scenes
///
public void RemoveFromPhysicalScene()
{
- if (PhysicsActor != null)
+ PhysicsActor pa = Interlocked.Exchange(ref m_physActor, null);
+ if (pa != null)
{
// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
- PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
- PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
- PhysicsActor.UnSubscribeEvents();
- m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
- PhysicsActor = null;
+ pa.OnOutOfBounds -= OutOfBoundsCall;
+ pa.OnCollisionUpdate -= PhysicsCollisionUpdate;
+ pa.UnSubscribeEvents();
+ m_scene.PhysicsScene.RemoveAvatar(pa);
}
// else
// {
@@ -2537,7 +2554,7 @@ namespace OpenSim.Region.Framework.Scenes
m_pos.X = 127f;
m_pos.Y = 127f;
m_pos.Z = 127f;
- m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
+ m_log.Error("[AVATAR]: NonFinite Avatar on lastFiniteposition also. Reset Position. Mantis this please. Error #9999903");
}
if(isphysical)
@@ -5007,16 +5024,17 @@ namespace OpenSim.Region.Framework.Scenes
PhysicsScene scene = m_scene.PhysicsScene;
Vector3 pVec = AbsolutePosition;
- PhysicsActor = scene.AddAvatar(
+ PhysicsActor pa = scene.AddAvatar(
LocalId, Firstname + "." + Lastname, pVec,
Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying);
- PhysicsActor.Orientation = m_bodyRot;
+ pa.Orientation = m_bodyRot;
//PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
- PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
- PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
- PhysicsActor.SubscribeEvents(100);
- PhysicsActor.LocalID = LocalId;
- PhysicsActor.SetAlwaysRun = m_setAlwaysRun;
+ pa.OnCollisionUpdate += PhysicsCollisionUpdate;
+ pa.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
+ pa.SubscribeEvents(100);
+ pa.LocalID = LocalId;
+ pa.SetAlwaysRun = m_setAlwaysRun;
+ PhysicsActor = pa;
}
private void OutOfBoundsCall(Vector3 pos)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index a60381afb7..020c7bed99 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return iout;
}
+/*
// new using terrain data and patchs indexes
public static List CreateLayerDataPackets(TerrainData terrData, int[] map)
{
@@ -213,6 +214,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return ret;
}
+*/
public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
{
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index 516f9eb4bd..822439fb5e 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -323,7 +323,7 @@ namespace OpenSim.Region.OptionalModules.Materials
}
if(facechanged)
- part.Shape.TextureEntry = te.GetBytes();
+ part.Shape.TextureEntry = te.GetBytes(9);
if(facechanged || partchanged)
{
@@ -632,7 +632,7 @@ namespace OpenSim.Region.OptionalModules.Materials
faceEntry.MaterialID = id;
//m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
- sop.Shape.TextureEntry = te.GetBytes();
+ sop.Shape.TextureEntry = te.GetBytes(9);
}
if(oldid != UUID.Zero)
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs b/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs
index 40c6b983b0..4e9216db30 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs
@@ -47,9 +47,9 @@ public class BSActorAvatarMove : BSActor
// The amount the step up is applying. Used to smooth stair walking.
float m_lastStepUp;
- // There are times the velocity is set but we don't want to inforce stationary until the
- // real velocity drops.
- bool m_waitingForLowVelocityForStationary = false;
+ // There are times the velocity or force is set but we don't want to inforce
+ // stationary until some tick in the future and the real velocity drops.
+ int m_waitingForLowVelocityForStationary = 0;
public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
: base(physicsScene, pObj, actorName)
@@ -114,14 +114,18 @@ public class BSActorAvatarMove : BSActor
m_velocityMotor.Enabled = true;
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,SetVelocityAndTarget,vel={1}, targ={2}",
m_controllingPrim.LocalID, vel, targ);
- m_waitingForLowVelocityForStationary = false;
+ m_waitingForLowVelocityForStationary = 0;
}
});
}
public void SuppressStationayCheckUntilLowVelocity()
{
- m_waitingForLowVelocityForStationary = true;
+ m_waitingForLowVelocityForStationary = 1;
+ }
+ public void SuppressStationayCheckUntilLowVelocity(int waitTicks)
+ {
+ m_waitingForLowVelocityForStationary = waitTicks;
}
// If a movement motor has not been created, create one and start the movement
@@ -143,7 +147,7 @@ public class BSActorAvatarMove : BSActor
m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
m_walkingUpStairs = 0;
- m_waitingForLowVelocityForStationary = false;
+ m_waitingForLowVelocityForStationary = 0;
}
}
@@ -194,15 +198,17 @@ public class BSActorAvatarMove : BSActor
// if colliding with something stationary and we're not doing volume detect .
if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect)
{
- if (m_waitingForLowVelocityForStationary)
+ if (m_waitingForLowVelocityForStationary-- <= 0)
{
// if waiting for velocity to drop and it has finally dropped, we can be stationary
+ // m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,waitingForLowVelocity {1}",
+ // m_controllingPrim.LocalID, m_waitingForLowVelocityForStationary);
if (m_controllingPrim.RawVelocity.LengthSquared() < BSParam.AvatarStopZeroThresholdSquared)
{
- m_waitingForLowVelocityForStationary = false;
+ m_waitingForLowVelocityForStationary = 0;
}
}
- if (!m_waitingForLowVelocityForStationary)
+ if (m_waitingForLowVelocityForStationary <= 0)
{
m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
m_controllingPrim.IsStationary = true;
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
old mode 100644
new mode 100755
index 2ca7dbc498..f971e59166
--- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
@@ -701,7 +701,7 @@ public sealed class BSCharacter : BSPhysObject
}
if (m_moveActor != null)
{
- m_moveActor.SuppressStationayCheckUntilLowVelocity();
+ m_moveActor.SuppressStationayCheckUntilLowVelocity(BSParam.AvatarAddForceFrames);
}
});
}
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs
index 495f752e46..d80b050de6 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs
@@ -149,6 +149,7 @@ public static class BSParam
public static float AvatarHeightHighFudge { get; private set; }
public static float AvatarFlyingGroundMargin { get; private set; }
public static float AvatarFlyingGroundUpForce { get; private set; }
+ public static int AvatarAddForceFrames { get; private set; }
public static float AvatarTerminalVelocity { get; private set; }
public static float AvatarContactProcessingThreshold { get; private set; }
public static float AvatarAddForcePushFactor { get; private set; }
@@ -634,6 +635,8 @@ public static class BSParam
5f ),
new ParameterDefn("AvatarFlyingGroundUpForce", "Upward force applied to the avatar to keep it at flying ground margin",
2.0f ),
+ new ParameterDefn("AvatarAddForceFrames", "Frames to allow AddForce to apply before checking for stationary",
+ 10 ),
new ParameterDefn("AvatarTerminalVelocity", "Terminal Velocity of falling avatar",
-54.0f ),
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
old mode 100644
new mode 100755
index 3120d04038..a6a2dd890e
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -221,7 +221,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
///
private static void CmdHandlerThreadLoop()
{
- while (true)
+ bool running = true;
+ while (running)
{
try
{
@@ -230,7 +231,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
DoOneCmdHandlerPass();
Watchdog.UpdateThread();
}
- catch ( System.Threading.ThreadAbortException) { }
+ catch ( System.Threading.ThreadAbortException)
+ {
+ Thread.ResetAbort();
+ running = false;
+ }
catch (Exception e)
{
m_log.Error("[ASYNC COMMAND MANAGER]: Exception in command handler pass: ", e);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 943141cba3..ab3562f35b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -1936,45 +1936,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
- Primitive.TextureEntry tex = part.Shape.Textures;
- int nsides = GetNumberOfSides(part);
- Color4 texcolor;
-
- if (face >= 0 && face < nsides)
- {
- texcolor = tex.CreateFace((uint)face).RGBA;
- texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
- texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
- texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
- tex.FaceTextures[face].RGBA = texcolor;
- part.UpdateTextureEntry(tex);
- return;
- }
- else if (face == ScriptBaseClass.ALL_SIDES)
- {
- for (uint i = 0; i < nsides; i++)
- {
- if (tex.FaceTextures[i] != null)
- {
- texcolor = tex.FaceTextures[i].RGBA;
- texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
- texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
- texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
- tex.FaceTextures[i].RGBA = texcolor;
- }
- texcolor = tex.DefaultTexture.RGBA;
- texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
- texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
- texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
- tex.DefaultTexture.RGBA = texcolor;
- }
- part.UpdateTextureEntry(tex);
- return;
- }
-
- if (face == ScriptBaseClass.ALL_SIDES)
- face = SceneObjectPart.ALL_SIDES;
-
m_host.SetFaceColorAlpha(face, color, null);
}
@@ -3577,7 +3538,7 @@ 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);
- if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
+ if (string.IsNullOrEmpty(inventory) || Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
return;
float dist = (float)llVecDist(llGetPos(), pos);
@@ -10653,7 +10614,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return false;
texface.MaterialID = id;
- part.Shape.TextureEntry = tex.GetBytes();
+ part.Shape.TextureEntry = tex.GetBytes(9);
m_materialsModule.RemoveMaterial(oldid);
return true;
}
@@ -10710,7 +10671,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return false;
texface.MaterialID = id;
- part.Shape.TextureEntry = tex.GetBytes();
+ part.Shape.TextureEntry = tex.GetBytes(9);
m_materialsModule.RemoveMaterial(oldid);
return true;
}
@@ -10777,7 +10738,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return false;
texface.MaterialID = id;
- part.Shape.TextureEntry = tex.GetBytes();
+ part.Shape.TextureEntry = tex.GetBytes(9);
m_materialsModule.RemoveMaterial(oldid);
return true;
}
@@ -13945,14 +13906,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Key llHTTPRequest(string url, LSL_List parameters, string body)
{
- // Partial implementation: support for parameter flags needed
- // see http://wiki.secondlife.com/wiki/LlHTTPRequest
- // parameter flags support are implemented in ScriptsHttpRequests.cs
- // in StartHttpRequest
-
m_host.AddScriptLPS(1);
- IHttpRequestModule httpScriptMod =
- m_ScriptEngine.World.RequestModuleInterface();
+ IHttpRequestModule httpScriptMod = m_ScriptEngine.World.RequestModuleInterface();
+ if(httpScriptMod == null)
+ return "";
+
+ if(!httpScriptMod.CheckThrottle(m_host.LocalId, m_host.OwnerID))
+ return UUID.Zero.ToString();
+
List param = new List();
bool ok;
Int32 flag;
@@ -14123,8 +14084,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
HttpInitialRequestStatus status;
- UUID reqID
- = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
+ UUID reqID = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER)
Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url));
@@ -14132,7 +14092,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (reqID != UUID.Zero)
return reqID.ToString();
else
- return null;
+ return "";
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 9d5f67014c..dabd399b0a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3629,7 +3629,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
- World.ForEachRootScenePresence(delegate(ScenePresence sp)
+ World.ForEachRootScenePresence(delegate (ScenePresence sp)
{
if (sp.Firstname == FirstName && sp.Lastname == SurName)
{
@@ -3643,18 +3643,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
});
}
- public LSL_Float osGetHealth(string avatar)
+ public void osKickAvatar(LSL_Key agentKey, string alert)
+ {
+ CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
+
+ UUID id;
+ if (!UUID.TryParse(agentKey, out id) || id == UUID.Zero)
+ return;
+
+ ScenePresence sp = World.GetScenePresence(id);
+ if(sp == null)
+ return;
+
+ // kick client...
+ if (alert != null)
+ sp.ControllingClient.Kick(alert);
+
+ // ...and close on our side
+ sp.Scene.CloseAgent(id, false);
+ }
+
+ public LSL_Float osGetHealth(LSL_Key agentKey)
{
CheckThreatLevel(ThreatLevel.None, "osGetHealth");
LSL_Float health = new LSL_Float(-1);
- ScenePresence presence = World.GetScenePresence(new UUID(avatar));
+
+ UUID id;
+ if (!UUID.TryParse(agentKey, out id) || id == UUID.Zero)
+ return health;
+
+ ScenePresence presence = World.GetScenePresence(id);
if (presence != null)
health = presence.Health;
return health;
}
- public void osCauseDamage(string avatar, double damage)
+ public void osCauseDamage(LSL_Key avatar, LSL_Float damage)
{
CheckThreatLevel(ThreatLevel.High, "osCauseDamage");
@@ -3683,7 +3708,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
- public void osCauseHealing(string avatar, double healing)
+ public void osCauseHealing(LSL_Key avatar, LSL_Float healing)
{
CheckThreatLevel(ThreatLevel.High, "osCauseHealing");
@@ -3704,7 +3729,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
presence.setHealthWithUpdate(health);
}
- public void osSetHealth(string avatar, double health)
+ public void osSetHealth(LSL_Key avatar, LSL_Float health)
{
CheckThreatLevel(ThreatLevel.High, "osSetHealth");
@@ -3722,7 +3747,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
- public void osSetHealRate(string avatar, double healrate)
+ public void osSetHealRate(LSL_Key avatar, LSL_Float healrate)
{
CheckThreatLevel(ThreatLevel.High, "osSetHealRate");
@@ -3737,7 +3762,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
presence.HealRate = (float)healrate;
}
- public LSL_Float osGetHealRate(string avatar)
+ public LSL_Float osGetHealRate(LSL_Key avatar)
{
CheckThreatLevel(ThreatLevel.None, "osGetHealRate");
@@ -3864,29 +3889,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return date.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
}
- ///
- /// Get the description from an inventory item
- ///
- ///
- /// Item description
- public LSL_String osGetInventoryDesc(string item)
- {
- CheckThreatLevel();
-
- lock (m_host.TaskInventory)
- {
- foreach (KeyValuePair inv in m_host.TaskInventory)
- {
- if (inv.Value.Name == item)
- {
- return inv.Value.Description.ToString();
- }
- }
- }
-
- return String.Empty;
- }
-
///
/// Invite user to the group this object is set to
///
@@ -4849,8 +4851,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return Math.Atan2(mcross, dot);
}
-
-//******* link sound
public void osAdjustSoundVolume(LSL_Integer linknum, LSL_Float volume)
{
m_host.AddScriptLPS(1);
@@ -5381,5 +5381,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return 1;
}
+ public LSL_Key osGetInventoryLastOwner(LSL_String itemNameorid)
+ {
+ m_host.AddScriptLPS(1);
+
+ TaskInventoryItem item = null;
+ UUID itemID;
+ if (UUID.TryParse(itemNameorid, out itemID))
+ item = m_host.Inventory.GetInventoryItem(itemID);
+ else
+ item = m_host.Inventory.GetInventoryItem(itemNameorid);
+
+ if (item == null)
+ return UUID.Zero.ToString();
+
+ UUID id = item.LastOwnerID;
+ if(id == UUID.Zero)
+ id= item.OwnerID;
+ return id.ToString();
+ }
+
+ public LSL_String osGetInventoryName(LSL_Key itemId)
+ {
+ m_host.AddScriptLPS(1);
+
+ TaskInventoryItem item = null;
+ UUID itemID;
+ if (UUID.TryParse(itemId, out itemID))
+ item = m_host.Inventory.GetInventoryItem(itemID);
+
+ if (item == null)
+ return String.Empty;
+
+ return item.Name;
+ }
+
+ public LSL_String osGetInventoryDesc(LSL_String itemNameorid)
+ {
+ m_host.AddScriptLPS(1);
+
+ TaskInventoryItem item = null;
+ UUID itemID;
+ if (UUID.TryParse(itemNameorid, out itemID))
+ item = m_host.Inventory.GetInventoryItem(itemID);
+ else
+ item = m_host.Inventory.GetInventoryItem(itemNameorid);
+
+ if (item == null)
+ return String.Empty;
+
+ return item.Description;
+ }
+
+ public LSL_Key osGetLastChangedEventKey()
+ {
+ m_host.AddScriptLPS(1);
+ DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
+ if (detectedParams == null)
+ return String.Empty;
+ return detectedParams.Key.ToString();
+ }
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs
index 629b14bbb2..166f2d9814 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs
@@ -48,14 +48,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
if (m_CmdManager.m_ScriptEngine.World == null)
return;
- IHttpRequestModule iHttpReq =
- m_CmdManager.m_ScriptEngine.World.RequestModuleInterface();
-
- HttpRequestClass httpInfo = null;
-
- if (iHttpReq != null)
- httpInfo = (HttpRequestClass)iHttpReq.GetNextCompletedRequest();
+ IHttpRequestModule iHttpReq = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface();
+ if(iHttpReq == null)
+ return;
+ HttpRequestClass httpInfo = (HttpRequestClass)iHttpReq.GetNextCompletedRequest();
while (httpInfo != null)
{
//m_log.Debug("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status);
@@ -67,8 +64,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
// implemented here yet anyway. Should be fixed if/when maxsize
// is supported
- iHttpReq.RemoveCompletedRequest(httpInfo.ReqID);
-
object[] resobj = new object[]
{
new LSL_Types.LSLString(httpInfo.ReqID.ToString()),
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 12e8103b3d..49b3f74e8c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -379,15 +379,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
int osGetSimulatorMemory();
int osGetSimulatorMemoryKB();
- void osKickAvatar(string FirstName,string SurName,string alert);
+ void osKickAvatar(string FirstName, string SurName, string alert);
+ void osKickAvatar(LSL_Key agentId, string alert);
void osSetSpeed(string UUID, LSL_Float SpeedModifier);
void osSetOwnerSpeed(LSL_Float SpeedModifier);
- LSL_Float osGetHealth(string avatar);
- void osCauseHealing(string avatar, double healing);
- void osSetHealth(string avatar, double health);
- void osSetHealRate(string avatar, double health);
- LSL_Float osGetHealRate(string avatar);
- void osCauseDamage(string avatar, double damage);
+ LSL_Float osGetHealth(key agentId);
+ void osCauseHealing(key agentId, LSL_Float healing);
+ void osSetHealth(key agentId, LSL_Float health);
+ void osSetHealRate(key agentId, LSL_Float health);
+ LSL_Float osGetHealRate(key agentId);
+ void osCauseDamage(key avatar, LSL_Float damage);
void osForceOtherSit(string avatar);
void osForceOtherSit(string avatar, string target);
LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
@@ -400,8 +401,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_String osUnixTimeToTimestamp(LSL_Integer time);
- LSL_String osGetInventoryDesc(string item);
-
LSL_Integer osInviteToGroup(LSL_Key agentId);
LSL_Integer osEjectFromGroup(LSL_Key agentId);
@@ -546,5 +545,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_Integer osApproxEquals(vector va, vector vb, LSL_Float margin);
LSL_Integer osApproxEquals(rotation ra, rotation rb);
LSL_Integer osApproxEquals(rotation ra, rotation rb, LSL_Float margin);
+ LSL_Key osGetInventoryLastOwner(LSL_String itemNameOrId);
+ LSL_String osGetInventoryName(LSL_Key itemId);
+ LSL_String osGetInventoryDesc(LSL_String itemNameOrId);
+ LSL_Key osGetLastChangedEventKey();
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 49f46b7b4c..8b70128e71 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -35,7 +35,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public partial class ScriptBaseClass
{
// SCRIPTS CONSTANTS
- public static readonly LSLInteger OS_APIVERSION = 2;
+ public static readonly LSLInteger OS_APIVERSION = 3;
public static readonly LSLInteger TRUE = 1;
public static readonly LSLInteger FALSE = 0;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 94df1eaa76..fb491e4923 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -965,11 +965,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osGetSimulatorMemoryKB();
}
- public void osKickAvatar(string FirstName,string SurName,string alert)
+ public void osKickAvatar(string FirstName, string SurName, string alert)
{
m_OSSL_Functions.osKickAvatar(FirstName, SurName, alert);
}
+ public void osKickAvatar(LSL_Key agentId, string alert)
+ {
+ m_OSSL_Functions.osKickAvatar(agentId, alert);
+ }
+
public void osSetSpeed(string UUID, LSL_Float SpeedModifier)
{
m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
@@ -980,32 +985,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_OSSL_Functions.osSetOwnerSpeed(SpeedModifier);
}
- public LSL_Float osGetHealth(string avatar)
+ public LSL_Float osGetHealth(key avatar)
{
return m_OSSL_Functions.osGetHealth(avatar);
}
- public void osCauseDamage(string avatar, double damage)
+ public void osCauseDamage(key avatar, LSL_Float damage)
{
m_OSSL_Functions.osCauseDamage(avatar, damage);
}
- public void osCauseHealing(string avatar, double healing)
+ public void osCauseHealing(key avatar, LSL_Float healing)
{
m_OSSL_Functions.osCauseHealing(avatar, healing);
}
- public void osSetHealth(string avatar, double health)
+ public void osSetHealth(key avatar, LSL_Float health)
{
m_OSSL_Functions.osSetHealth(avatar, health);
}
- public void osSetHealRate(string avatar, double health)
+ public void osSetHealRate(key avatar, LSL_Float health)
{
m_OSSL_Functions.osSetHealRate(avatar, health);
}
- public LSL_Float osGetHealRate(string avatar)
+ public LSL_Float osGetHealRate(key avatar)
{
return m_OSSL_Functions.osGetHealRate(avatar);
}
@@ -1055,11 +1060,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osUnixTimeToTimestamp(time);
}
- public LSL_String osGetInventoryDesc(string item)
- {
- return m_OSSL_Functions.osGetInventoryDesc(item);
- }
-
public LSL_Integer osInviteToGroup(LSL_Key agentId)
{
return m_OSSL_Functions.osInviteToGroup(agentId);
@@ -1361,5 +1361,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
return m_OSSL_Functions.osApproxEquals(ra, rb, margin);
}
+
+ public LSL_Key osGetInventoryLastOwner(LSL_String itemNameOrId)
+ {
+ return m_OSSL_Functions.osGetInventoryLastOwner(itemNameOrId);
+ }
+
+ public LSL_String osGetInventoryName(LSL_Key itemId)
+ {
+ return m_OSSL_Functions.osGetInventoryName(itemId);
+ }
+
+ public LSL_String osGetInventoryDesc(LSL_String itemNameOrId)
+ {
+ return m_OSSL_Functions.osGetInventoryDesc(itemNameOrId);
+ }
+
+ public LSL_Key osGetLastChangedEventKey()
+ {
+ return m_OSSL_Functions.osGetLastChangedEventKey();
+ }
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 019a0d9986..351fca9bed 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -699,7 +699,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// If min event delay is set then ignore any events untill the time has expired
// This currently only allows 1 event of any type in the given time period.
// This may need extending to allow for a time for each individual event type.
- if (m_eventDelayTicks != 0)
+ if (m_eventDelayTicks != 0 &&
+ data.EventName != "state" && data.EventName != "state_entry" && data.EventName != "state_exit"
+ && data.EventName != "run_time_permissions" && data.EventName != "http_request" && data.EventName != "link_message")
{
if (DateTime.Now.Ticks < m_nextEventTimeTicks)
return;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index b7fc161e61..50a95a90ee 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -215,12 +215,25 @@ namespace OpenSim.Region.ScriptEngine.XEngine
det));
}
- public void changed(uint localID, uint change)
+ public void changed(uint localID, uint change, object parameter)
{
// Add to queue for all scripts in localID, Object pass change.
- myScriptEngine.PostObjectEvent(localID, new EventParams(
- "changed",new object[] { new LSL_Types.LSLInteger(change) },
+ if(parameter == null)
+ {
+ myScriptEngine.PostObjectEvent(localID, new EventParams(
+ "changed", new object[] { new LSL_Types.LSLInteger(change) },
new DetectParams[0]));
+ return;
+ }
+ if (parameter is UUID)
+ {
+ DetectParams det = new DetectParams();
+ det.Key = (UUID)parameter;
+ myScriptEngine.PostObjectEvent(localID, new EventParams(
+ "changed", new object[] { new LSL_Types.LSLInteger(change) },
+ new DetectParams[] { det }));
+ return;
+ }
}
// state_entry: not processed here
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs
index c00e8d4dda..3539fa13b9 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs
@@ -88,10 +88,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
path_update = 40,
- // XMRE specific
- region_cross = 63,
-
// marks highest numbered event, ie, number of columns in seht.
- Size = 64
+ Size = 41
}
}
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs
index 017b294d6b..6acc293869 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs
@@ -930,12 +930,15 @@ namespace OpenSim.Region.ScriptEngine.Yengine
public void SetMinEventDelay(UUID itemID, double delay)
{
+ XMRInstance instance = GetInstance(itemID);
+ if (instance != null)
+ instance.MinEventDelay = delay;
}
public int GetStartParameter(UUID itemID)
{
XMRInstance instance = GetInstance(itemID);
- if(instance == null)
+ if (instance == null)
return 0;
return instance.StartParam;
}
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs
index 5a8b2a39aa..65a8aed88b 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs
@@ -182,13 +182,26 @@ namespace OpenSim.Region.ScriptEngine.Yengine
new DetectParams[] { det }));
}
- public void changed(uint localID, uint change)
+ public void changed(uint localID, uint change, object parameter)
{
int ch = (int)change;
// Add to queue for all scripts in localID, Object pass change.
- this.PostObjectEvent(localID, new EventParams(
+ if(parameter == null)
+ {
+ PostObjectEvent(localID, new EventParams(
"changed", new object[] { ch },
zeroDetectParams));
+ return;
+ }
+ if ( parameter is UUID)
+ {
+ DetectParams det = new DetectParams();
+ det.Key = (UUID)parameter;
+ PostObjectEvent(localID, new EventParams(
+ "changed", new object[] { ch },
+ new DetectParams[] { det }));
+ return;
+ }
}
// state_entry: not processed here
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs
index 6fe11d8113..7fc97e9c1a 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs
@@ -422,9 +422,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
object[] saveEHArgs = this.ehArgs;
ScriptEventCode saveEventCode = this.eventCode;
- this.m_DetectParams = evt.DetectParams;
- this.ehArgs = evt.Params;
- this.eventCode = evc;
+ m_DetectParams = evt.DetectParams;
+ ehArgs = evt.Params;
+ eventCode = evc;
try
{
@@ -432,9 +432,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
}
finally
{
- this.m_DetectParams = saveDetParams;
- this.ehArgs = saveEHArgs;
- this.eventCode = saveEventCode;
+ m_DetectParams = saveDetParams;
+ ehArgs = saveEHArgs;
+ eventCode = saveEventCode;
}
// Keep waiting until we find a returnable event or timeout.
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs
index 9bb894de2c..5798638623 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs
@@ -115,6 +115,15 @@ namespace OpenSim.Region.ScriptEngine.Yengine
m_RunOnePhase = "GetExecutionState D";
CheckRunLockInvariants(true);
+ if (m_minEventDelay != 0.0)
+ {
+ XmlElement minEventDelayN = doc.CreateElement("", "mEvtDly", "");
+ minEventDelayN.AppendChild(doc.CreateTextNode(m_minEventDelay.ToString()));
+ scriptStateN.AppendChild(minEventDelayN);
+ m_RunOnePhase = "GetExecutionState D";
+ CheckRunLockInvariants(true);
+ }
+
// More misc data.
XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
scriptStateN.AppendChild(permissionsN);
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs
index b140453b83..7e13ae4962 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs
@@ -527,6 +527,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
XmlElement doGblInitN = (XmlElement)scriptStateN.SelectSingleNode("DoGblInit");
doGblInit = bool.Parse(doGblInitN.InnerText);
+ double minEventDelay = 0.0;
+ XmlElement minEventDelayN = (XmlElement)scriptStateN.SelectSingleNode("mEvtDly");
+ if(minEventDelayN != null)
+ minEventDelay = Double.Parse(minEventDelayN.InnerText);
+
// get values used by stuff like llDetectedGrab, etc.
DetectParams[] detParams = RestoreDetectParams(scriptStateN.SelectSingleNode("DetectArray"));
@@ -576,6 +581,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
AsyncCommandManager.CreateFromData(m_Engine,
m_LocalID, m_ItemID, m_Part.UUID,
pluginData);
+
+ MinEventDelay = minEventDelay;
}
private void processXstate(XmlDocument doc)
@@ -919,6 +926,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
AsyncCommandManager.CreateFromData(m_Engine,
m_LocalID, m_ItemID, m_Part.UUID, pluginData);
+
+ MinEventDelay = minEventDelay;
}
private static void getvarNames(Dictionary s, Dictionary d)
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs
index 3c0040c84a..def06b27c5 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs
@@ -215,5 +215,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
// It's born ready, but will be reset when the detach is posted.
// It will then be set again on suspend/completion
private ManualResetEvent m_DetachReady = new ManualResetEvent(true);
+
+ // llmineventdelay support
+ double m_minEventDelay = 0.0;
+ double m_nextEventTime = 0.0;
}
}
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs
index 0af3d37c3a..12feb7b428 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs
@@ -298,6 +298,24 @@ namespace OpenSim.Region.ScriptEngine.Yengine
}
}
+ public double MinEventDelay
+ {
+ get
+ {
+ return m_minEventDelay;
+ }
+ set
+ {
+ if (value > 0.001)
+ m_minEventDelay = value;
+ else
+ m_minEventDelay = 0.0;
+
+ m_nextEventTime = 0.0; // reset it
+ }
+ }
+
+
public SceneObjectPart SceneObject
{
get
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs
index 6c969dc697..1b735e33de 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs
@@ -63,8 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
*/
public void PostEvent(EventParams evt)
{
- ScriptEventCode evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode),
- evt.EventName);
+ ScriptEventCode evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt.EventName);
// Put event on end of event queue.
bool startIt = false;
@@ -86,6 +85,47 @@ namespace OpenSim.Region.ScriptEngine.Yengine
if(!m_Running && !construct)
return;
+ if(m_minEventDelay != 0)
+ {
+ switch (evc)
+ {
+ // ignore some events by time set by llMinEventDelay
+ case ScriptEventCode.collision:
+ case ScriptEventCode.land_collision:
+ case ScriptEventCode.listen:
+ case ScriptEventCode.not_at_target:
+ case ScriptEventCode.not_at_rot_target:
+ case ScriptEventCode.no_sensor:
+ case ScriptEventCode.sensor:
+ case ScriptEventCode.timer:
+ case ScriptEventCode.touch:
+ {
+ double now = Util.GetTimeStamp();
+ if (now < m_nextEventTime)
+ return;
+ m_nextEventTime = now + m_minEventDelay;
+ break;
+ }
+ case ScriptEventCode.changed:
+ {
+ const int canignore = ~(CHANGED_SCALE | CHANGED_POSITION);
+ int change = (int)evt.Params[0];
+ if(change == 0) // what?
+ return;
+ if((change & canignore) == 0)
+ {
+ double now = Util.GetTimeStamp();
+ if (now < m_nextEventTime)
+ return;
+ m_nextEventTime = now + m_minEventDelay;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
// Only so many of each event type allowed to queue.
if((uint)evc < (uint)m_EventCounts.Length)
{
@@ -124,10 +164,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
for(lln2 = m_EventQueue.First; lln2 != null; lln2 = lln2.Next)
{
EventParams evt2 = lln2.Value;
- ScriptEventCode evc2 = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode),
- evt2.EventName);
- if((evc2 != ScriptEventCode.state_entry) &&
- (evc2 != ScriptEventCode.attach))
+ ScriptEventCode evc2 = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt2.EventName);
+ if((evc2 != ScriptEventCode.state_entry) && (evc2 != ScriptEventCode.attach))
break;
}
if(lln2 == null)
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 0438673ce3..22748cc1f7 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -757,6 +757,14 @@ namespace OpenSim.Services.LLLoginService
}
}
}
+
+ //find a exact match
+ foreach(GridRegion r in regions)
+ {
+ if(string.Equals(regionName, r.RegionName, StringComparison.InvariantCultureIgnoreCase))
+ return r;
+ }
+ // else, whatever
return regions[0];
}
else
diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll
index b7ddd0bd18..02edd6c1d3 100755
Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 3a80dbedd9..cede84d25b 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -661,6 +661,25 @@
; many simultaneous requests, default is 30 and is currently applied only to assets
;MaxRequestConcurrency = 30
+[ScriptsHttpRequestModule]
+ ; options for llHttpRequest
+
+ ; max number of concurrent connections per instance (all scenes), default 8
+ ; MaxPoolThreads = 8
+
+ ; max requests per second for all scripts on a prim, default 1
+ ;PrimRequestsPerSec = 1.0
+ ; initial unthrottled burst for all scripts on a prim, default 3
+ ;PrimRequestsBurst = 3.0
+
+ ; max requests per second for the objects owner (per instance), default 25
+ ;PrimOwnerRequestsPerSec = 25.0
+ ; initial unthrottled burst for the objects owner (per instance), default 5
+ ;PrimOwnerRequestsBurst = 5.0
+
+ ; requests timeout in miliseconds, range 200 to 60000, default 30000
+ ;RequestsTimeOut = 30000
+
[AccessControl]
; Viewer-based access control. |-separated list of allowed viewers.
; AllowedClients = ""
@@ -728,17 +747,6 @@
;texture_default = 18500
;asset_default = 10500
- ; Configures how ObjectUpdates are aggregated. These numbers
- ; do not literally mean how many updates will be put in each
- ; packet that goes over the wire, as packets are
- ; automatically split on a 1400 byte boundary. These control
- ; the balance between responsiveness of interest list updates
- ; and total throughput. Higher numbers will ensure more full-
- ; sized packets and faster sending of data, but more delay in
- ; updating interest lists
- ;
- ;PrimUpdatesPerCallback = 100
-
; TextureSendLimit determines how many packets will be put on
; the outgoing queue each cycle. Like the settings above, this
; is a balance between responsiveness to priority updates and
@@ -748,16 +756,6 @@
;
;TextureSendLimit = 20
- ; CannibalizeTextureRate allows bandwidth to be moved from the
- ; UDP texture throttle to the task throttle. Since most viewers
- ; use HTTP textures, this provides a means of using what is largely
- ; unused bandwidth in the total throttle. The value is the proportion
- ; of the texture rate to move to the task queue. It must be between
- ; 0.0 (none of the bandwidth is cannibalized) and 0.9 (90% of the
- ; bandwidth is grabbed)
- ;
- ; CannibalizeTextureRate = 0.5
-
; Quash and remove any light properties from attachments not on the
; hands. This allows flashlights and lanterns to function, but kills
; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps
@@ -802,6 +800,7 @@
Cap_GetTexture = "localhost"
Cap_GetMesh = "localhost"
Cap_GetMesh2 = "localhost"
+ ; Cap_GetAsset = "localhost" DO not ucoment this line. Some popular viewers still dont do it right for opensim. Here to easy testing
Cap_GetObjectCost = ""
Cap_GetObjectPhysicsData = ""
Cap_GroupProposalBallot = ""
diff --git a/bin/ScriptSyntax.xml b/bin/ScriptSyntax.xml
index 862a66df93..8f2f6002f9 100644
--- a/bin/ScriptSyntax.xml
+++ b/bin/ScriptSyntax.xml
@@ -1,4 +1,4 @@
-a0b4b514-3c14-6b98-ca98-e18a79e9792f
+20392e48-fad2-094e-bc5b-cda003a1e940
osRegionRestart
@@ -7097,6 +7122,7 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
returninteger
arguments
secondstypefloat
+ msgtypestring
osReplaceString
@@ -7199,14 +7225,14 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
osSetHealRate
arguments
- avatartypestring
+ agentIdtypekey
healthtypefloat
osSetHealth
arguments
- avatartypestring
+ agentIdtypekey
healthtypefloat
@@ -7432,6 +7458,8 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
arguments
srctypestring
valuetypestring
+ starttypeinteger
+ counttypeinteger
ignorecasetypeinteger
@@ -7441,8 +7469,6 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
arguments
srctypestring
valuetypestring
- starttypeinteger
- counttypeinteger
ignorecasetypeinteger
@@ -7525,15 +7551,6 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
osTeleportAgent
-
- arguments
- agenttypestring
- regionNametypestring
- positiontypevector
- lookattypevector
-
-
- osTeleportAgent
arguments
agenttypestring
@@ -7551,6 +7568,15 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
lookattypevector
+ osTeleportAgent
+
+ arguments
+ agenttypestring
+ regionNametypestring
+ positiontypevector
+ lookattypevector
+
+
osTeleportObject
returninteger
@@ -7564,8 +7590,6 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
osTeleportOwner
arguments
- regionXtypeinteger
- regionYtypeinteger
positiontypevector
lookattypevector
@@ -7581,6 +7605,8 @@ a0b4b514-3c14-6b98-ca98-e18a79e9792f
osTeleportOwner
arguments
+ regionXtypeinteger
+ regionYtypeinteger
positiontypevector
lookattypevector
diff --git a/bin/config-include/osslEnable.ini b/bin/config-include/osslEnable.ini
index a96459ae82..f127b1fe3c 100644
--- a/bin/config-include/osslEnable.ini
+++ b/bin/config-include/osslEnable.ini
@@ -155,7 +155,6 @@
Allow_osForceDropAttachmentAt = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetLinkPrimitiveParams = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetPhysicsEngineType = true
- Allow_osGetPrimitiveParams = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetRegionMapTexture = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
Allow_osGetScriptEngineName = true
Allow_osGetSimulatorVersion = true
@@ -185,7 +184,6 @@
Allow_osParcelSubdivide = ESTATE_MANAGER,ESTATE_OWNER
Allow_osRegionRestart = ESTATE_MANAGER,ESTATE_OWNER
Allow_osRegionNotice = ESTATE_MANAGER,ESTATE_OWNER
- Allow_osSetPrimitiveParams = false
Allow_osSetProjectionParams = ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
Allow_osSetRegionWaterHeight = ESTATE_MANAGER,ESTATE_OWNER
Allow_osSetStateEvents = false ; deprecated
@@ -250,6 +248,7 @@
; Allow_osGetLinkNumber = true
; Allow_osGetMapTexture = true
; Allow_osGetPhysicsEngineName = true
+; Allow_osGetPrimitiveParams = true
; Allow_osGetRegionSize = true
; Allow_osGetSunParam = true
; Allow_osGetTerrainHeight = true
@@ -275,6 +274,7 @@
; Allow_osSetPenCap = true
; Allow_osSetPenColor = true
; Allow_osSetPenSize = true
+; Allow_osSetPrimitiveParams = true
; Allow_osSetSoundRadius = true
; Allow_osStopSound = true
; Allow_osStringSubString = true