aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs5
-rwxr-xr-xOpenSim/Data/PGSQL/PGSQLSimulationData.cs5
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs5
-rw-r--r--OpenSim/Framework/ClientManager.cs65
-rw-r--r--OpenSim/Framework/IClientAPI.cs3
-rwxr-xr-x[-rw-r--r--]OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs32
-rw-r--r--OpenSim/Framework/TerrainData.cs1
-rw-r--r--OpenSim/Framework/Util.cs28
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs39
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs23
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1158
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs90
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs350
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs37
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs279
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs182
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs14
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs28
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs253
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateModule.cs23
-rw-r--r--OpenSim/Region/Framework/Interfaces/IHttpRequests.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs164
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SceneGraph.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs33
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs4
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs24
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs2
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSParam.cs3
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs66
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs126
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs44
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs17
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs18
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs50
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs8
57 files changed, 2339 insertions, 1095 deletions
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index c5d7c47..3db30d8 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -1403,7 +1403,10 @@ namespace OpenSim.Data.MySQL
1403 1403
1404 prim.Sound = DBGuid.FromDB(row["LoopedSound"].ToString()); 1404 prim.Sound = DBGuid.FromDB(row["LoopedSound"].ToString());
1405 prim.SoundGain = (float)(double)row["LoopedSoundGain"]; 1405 prim.SoundGain = (float)(double)row["LoopedSoundGain"];
1406 prim.SoundFlags = 1; // If it's persisted at all, it's looped 1406 if (prim.Sound != UUID.Zero)
1407 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1408 else
1409 prim.SoundFlags = 0;
1407 1410
1408 if (!(row["TextureAnimation"] is DBNull)) 1411 if (!(row["TextureAnimation"] is DBNull))
1409 prim.TextureAnimation = (byte[])row["TextureAnimation"]; 1412 prim.TextureAnimation = (byte[])row["TextureAnimation"];
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
index 569cc80..99ceb91 100755
--- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
+++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
@@ -1742,7 +1742,10 @@ namespace OpenSim.Data.PGSQL
1742 1742
1743 prim.Sound = new UUID((Guid)primRow["LoopedSound"]); 1743 prim.Sound = new UUID((Guid)primRow["LoopedSound"]);
1744 prim.SoundGain = Convert.ToSingle(primRow["LoopedSoundGain"]); 1744 prim.SoundGain = Convert.ToSingle(primRow["LoopedSoundGain"]);
1745 prim.SoundFlags = 1; // If it's persisted at all, it's looped 1745 if (prim.Sound != UUID.Zero)
1746 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1747 else
1748 prim.SoundFlags = 0;
1746 1749
1747 if (!(primRow["TextureAnimation"] is DBNull)) 1750 if (!(primRow["TextureAnimation"] is DBNull))
1748 prim.TextureAnimation = (Byte[])primRow["TextureAnimation"]; 1751 prim.TextureAnimation = (Byte[])primRow["TextureAnimation"];
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index e02ac7d..1403a8f 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1742,7 +1742,10 @@ namespace OpenSim.Data.SQLite
1742 1742
1743 prim.Sound = new UUID(row["LoopedSound"].ToString()); 1743 prim.Sound = new UUID(row["LoopedSound"].ToString());
1744 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); 1744 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]);
1745 prim.SoundFlags = 1; // If it's persisted at all, it's looped 1745 if (prim.Sound != UUID.Zero)
1746 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1747 else
1748 prim.SoundFlags = 0;
1746 1749
1747 if (!row.IsNull("TextureAnimation")) 1750 if (!row.IsNull("TextureAnimation"))
1748 prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); 1751 prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString());
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs
index 45c54e4..1508c7f 100644
--- a/OpenSim/Framework/ClientManager.cs
+++ b/OpenSim/Framework/ClientManager.cs
@@ -51,7 +51,14 @@ namespace OpenSim.Framework
51 private object m_syncRoot = new object(); 51 private object m_syncRoot = new object();
52 52
53 /// <summary>Number of clients in the collection</summary> 53 /// <summary>Number of clients in the collection</summary>
54 public int Count { get { return m_dict1.Count; } } 54 public int Count
55 {
56 get
57 {
58 lock (m_syncRoot)
59 return m_dict1.Count;
60 }
61 }
55 62
56 /// <summary> 63 /// <summary>
57 /// Default constructor 64 /// Default constructor
@@ -60,7 +67,7 @@ namespace OpenSim.Framework
60 { 67 {
61 m_dict1 = new Dictionary<UUID, IClientAPI>(); 68 m_dict1 = new Dictionary<UUID, IClientAPI>();
62 m_dict2 = new Dictionary<IPEndPoint, IClientAPI>(); 69 m_dict2 = new Dictionary<IPEndPoint, IClientAPI>();
63 m_array = new IClientAPI[0]; 70 m_array = null;
64 } 71 }
65 72
66 /// <summary> 73 /// <summary>
@@ -74,17 +81,9 @@ namespace OpenSim.Framework
74 { 81 {
75 lock (m_syncRoot) 82 lock (m_syncRoot)
76 { 83 {
77 // allow self healing
78// if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint))
79// return false;
80
81 m_dict1[value.AgentId] = value; 84 m_dict1[value.AgentId] = value;
82 m_dict2[value.RemoteEndPoint] = value; 85 m_dict2[value.RemoteEndPoint] = value;
83 86 m_array = null;
84 // dict1 is the master
85 IClientAPI[] newArray = new IClientAPI[m_dict1.Count];
86 m_dict1.Values.CopyTo(newArray, 0);
87 m_array = newArray;
88 } 87 }
89 88
90 return true; 89 return true;
@@ -105,10 +104,7 @@ namespace OpenSim.Framework
105 { 104 {
106 m_dict1.Remove(key); 105 m_dict1.Remove(key);
107 m_dict2.Remove(value.RemoteEndPoint); 106 m_dict2.Remove(value.RemoteEndPoint);
108 107 m_array = null;
109 IClientAPI[] newArray = new IClientAPI[m_dict1.Count];
110 m_dict1.Values.CopyTo(newArray, 0);
111 m_array = newArray;
112 return true; 108 return true;
113 } 109 }
114 } 110 }
@@ -124,7 +120,7 @@ namespace OpenSim.Framework
124 { 120 {
125 m_dict1.Clear(); 121 m_dict1.Clear();
126 m_dict2.Clear(); 122 m_dict2.Clear();
127 m_array = new IClientAPI[0]; 123 m_array = null;
128 } 124 }
129 } 125 }
130 126
@@ -135,7 +131,8 @@ namespace OpenSim.Framework
135 /// <returns>True if the UUID was found in the collection, otherwise false</returns> 131 /// <returns>True if the UUID was found in the collection, otherwise false</returns>
136 public bool ContainsKey(UUID key) 132 public bool ContainsKey(UUID key)
137 { 133 {
138 return m_dict1.ContainsKey(key); 134 lock (m_syncRoot)
135 return m_dict1.ContainsKey(key);
139 } 136 }
140 137
141 /// <summary> 138 /// <summary>
@@ -145,7 +142,8 @@ namespace OpenSim.Framework
145 /// <returns>True if the endpoint was found in the collection, otherwise false</returns> 142 /// <returns>True if the endpoint was found in the collection, otherwise false</returns>
146 public bool ContainsKey(IPEndPoint key) 143 public bool ContainsKey(IPEndPoint key)
147 { 144 {
148 return m_dict2.ContainsKey(key); 145 lock (m_syncRoot)
146 return m_dict2.ContainsKey(key);
149 } 147 }
150 148
151 /// <summary> 149 /// <summary>
@@ -156,8 +154,12 @@ namespace OpenSim.Framework
156 /// <returns>True if the lookup succeeded, otherwise false</returns> 154 /// <returns>True if the lookup succeeded, otherwise false</returns>
157 public bool TryGetValue(UUID key, out IClientAPI value) 155 public bool TryGetValue(UUID key, out IClientAPI value)
158 { 156 {
159 try { return m_dict1.TryGetValue(key, out value); } 157 try
160 catch (Exception) 158 {
159 lock (m_syncRoot)
160 return m_dict1.TryGetValue(key, out value);
161 }
162 catch
161 { 163 {
162 value = null; 164 value = null;
163 return false; 165 return false;
@@ -172,8 +174,12 @@ namespace OpenSim.Framework
172 /// <returns>True if the lookup succeeded, otherwise false</returns> 174 /// <returns>True if the lookup succeeded, otherwise false</returns>
173 public bool TryGetValue(IPEndPoint key, out IClientAPI value) 175 public bool TryGetValue(IPEndPoint key, out IClientAPI value)
174 { 176 {
175 try { return m_dict2.TryGetValue(key, out value); } 177 try
176 catch (Exception) 178 {
179 lock (m_syncRoot)
180 return m_dict2.TryGetValue(key, out value);
181 }
182 catch
177 { 183 {
178 value = null; 184 value = null;
179 return false; 185 return false;
@@ -187,7 +193,20 @@ namespace OpenSim.Framework
187 /// <param name="action">Action to perform on each element</param> 193 /// <param name="action">Action to perform on each element</param>
188 public void ForEach(Action<IClientAPI> action) 194 public void ForEach(Action<IClientAPI> action)
189 { 195 {
190 IClientAPI[] localArray = m_array; 196 IClientAPI[] localArray;
197 lock (m_syncRoot)
198 {
199 if (m_array == null)
200 {
201 if (m_dict1.Count == 0)
202 return;
203
204 m_array = new IClientAPI[m_dict1.Count];
205 m_dict1.Values.CopyTo(m_array, 0);
206 }
207 localArray = m_array;
208 }
209
191 for (int i = 0; i < localArray.Length; i++) 210 for (int i = 0; i < localArray.Length; i++)
192 action(localArray[i]); 211 action(localArray[i]);
193 } 212 }
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 307dbf3..d63136e 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -390,7 +390,7 @@ namespace OpenSim.Framework
390 IClientAPI remoteClient, UUID invoice, UUID senderID, bool scripted, bool collisionEvents, bool physics); 390 IClientAPI remoteClient, UUID invoice, UUID senderID, bool scripted, bool collisionEvents, bool physics);
391 391
392 public delegate void EstateTeleportOneUserHomeRequest( 392 public delegate void EstateTeleportOneUserHomeRequest(
393 IClientAPI remoteClient, UUID invoice, UUID senderID, UUID prey); 393 IClientAPI remoteClient, UUID invoice, UUID senderID, UUID prey, bool kill);
394 394
395 public delegate void EstateTeleportAllUsersHomeRequest(IClientAPI remoteClient, UUID invoice, UUID senderID); 395 public delegate void EstateTeleportAllUsersHomeRequest(IClientAPI remoteClient, UUID invoice, UUID senderID);
396 396
@@ -671,7 +671,6 @@ namespace OpenSim.Framework
671 Particles = 1 << 19, 671 Particles = 1 << 19,
672 ExtraData = 1 << 20, 672 ExtraData = 1 << 20,
673 Sound = 1 << 21, 673 Sound = 1 << 21,
674 Joint = 1 << 22,
675 674
676 TerseUpdate = Position | Rotation | Velocity | Acceleration | AngularVelocity, 675 TerseUpdate = Position | Rotation | Velocity | Acceleration | AngularVelocity,
677 FullUpdate = 0x00ffffff, 676 FullUpdate = 0x00ffffff,
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index b9ac155..14e21a2 100644..100755
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -230,25 +230,25 @@ namespace OpenSim.Framework.Servers.HttpServer
230 PollServiceHttpRequest req; 230 PollServiceHttpRequest req;
231 while (m_running) 231 while (m_running)
232 { 232 {
233 req = null; 233 try
234 if(!m_requests.TryTake(out req, 4500) || req == null)
235 { 234 {
236 Watchdog.UpdateThread(); 235 req = null;
237 continue; 236 if (!m_requests.TryTake(out req, 4500) || req == null)
238 } 237 {
238 Watchdog.UpdateThread();
239 continue;
240 }
239 241
240 Watchdog.UpdateThread(); 242 Watchdog.UpdateThread();
241 243
242 try 244 if (!req.HttpContext.CanSend())
243 {
244 if(!req.HttpContext.CanSend())
245 { 245 {
246 req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id); 246 req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
247 byContextDequeue(req); 247 byContextDequeue(req);
248 continue; 248 continue;
249 } 249 }
250 250
251 if(req.HttpContext.IsSending()) 251 if (req.HttpContext.IsSending())
252 { 252 {
253 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 253 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
254 { 254 {
@@ -256,7 +256,7 @@ namespace OpenSim.Framework.Servers.HttpServer
256 byContextDequeue(req); 256 byContextDequeue(req);
257 } 257 }
258 else 258 else
259 ReQueueEvent(req); 259 ReQueueEvent(req);
260 continue; 260 continue;
261 } 261 }
262 262
@@ -290,7 +290,7 @@ namespace OpenSim.Framework.Servers.HttpServer
290 { 290 {
291 nreq.DoHTTPGruntWork(nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id)); 291 nreq.DoHTTPGruntWork(nreq.PollServiceArgs.NoEvents(nreq.RequestID, nreq.PollServiceArgs.Id));
292 } 292 }
293 catch (ObjectDisposedException) {} 293 catch (ObjectDisposedException) { }
294 finally 294 finally
295 { 295 {
296 byContextDequeue(nreq); 296 byContextDequeue(nreq);
@@ -305,6 +305,12 @@ namespace OpenSim.Framework.Servers.HttpServer
305 } 305 }
306 } 306 }
307 } 307 }
308 catch (ThreadAbortException)
309 {
310 Thread.ResetAbort();
311 // Shouldn't set this to 'false', the normal shutdown should cause things to exit
312 // m_running = false;
313 }
308 catch (Exception e) 314 catch (Exception e)
309 { 315 {
310 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); 316 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index 5604628..1a2d5d1 100644
--- a/OpenSim/Framework/TerrainData.cs
+++ b/OpenSim/Framework/TerrainData.cs
@@ -212,7 +212,6 @@ namespace OpenSim.Framework
212 return heights; 212 return heights;
213 } 213 }
214 214
215 // TerrainData.GetDoubles
216 public double[,] GetDoubles() 215 public double[,] GetDoubles()
217 { 216 {
218 double[,] ret = new double[SizeX, SizeY]; 217 double[,] ret = new double[SizeX, SizeY];
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 52f9aea..f66a987 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -2437,34 +2437,6 @@ namespace OpenSim.Framework
2437 2437
2438 #region FireAndForget Threading Pattern 2438 #region FireAndForget Threading Pattern
2439 2439
2440 /// <summary>
2441 /// Created to work around a limitation in Mono with nested delegates
2442 /// </summary>
2443 private sealed class FireAndForgetWrapper
2444 {
2445 private static object syncRoot = new Object();
2446
2447 public void FireAndForget(System.Threading.WaitCallback callback)
2448 {
2449 callback.BeginInvoke(null, EndFireAndForget, callback);
2450 }
2451
2452 public void FireAndForget(System.Threading.WaitCallback callback, object obj)
2453 {
2454 callback.BeginInvoke(obj, EndFireAndForget, callback);
2455 }
2456
2457 private static void EndFireAndForget(IAsyncResult ar)
2458 {
2459 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
2460
2461 try { callback.EndInvoke(ar); }
2462 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
2463
2464 ar.AsyncWaitHandle.Close();
2465 }
2466 }
2467
2468 public static void InitThreadPool(int minThreads, int maxThreads) 2440 public static void InitThreadPool(int minThreads, int maxThreads)
2469 { 2441 {
2470 if (maxThreads < 2) 2442 if (maxThreads < 2)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs
index 9187979..c071bd1 100644..100755
--- 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
59 private string m_GetTextureURL; 59 private string m_GetTextureURL;
60 private string m_GetMeshURL; 60 private string m_GetMeshURL;
61 private string m_GetMesh2URL; 61 private string m_GetMesh2URL;
62// private string m_GetAssetURL; 62 private string m_GetAssetURL;
63 63
64 class APollRequest 64 class APollRequest
65 { 65 {
@@ -87,7 +87,7 @@ namespace OpenSim.Region.ClientStack.Linden
87 private Dictionary<UUID, string> m_capsDictTexture = new Dictionary<UUID, string>(); 87 private Dictionary<UUID, string> m_capsDictTexture = new Dictionary<UUID, string>();
88 private Dictionary<UUID, string> m_capsDictGetMesh = new Dictionary<UUID, string>(); 88 private Dictionary<UUID, string> m_capsDictGetMesh = new Dictionary<UUID, string>();
89 private Dictionary<UUID, string> m_capsDictGetMesh2 = new Dictionary<UUID, string>(); 89 private Dictionary<UUID, string> m_capsDictGetMesh2 = new Dictionary<UUID, string>();
90 //private Dictionary<UUID, string> m_capsDictGetAsset = new Dictionary<UUID, string>(); 90 private Dictionary<UUID, string> m_capsDictGetAsset = new Dictionary<UUID, string>();
91 91
92 #region Region Module interfaceBase Members 92 #region Region Module interfaceBase Members
93 93
@@ -113,11 +113,11 @@ namespace OpenSim.Region.ClientStack.Linden
113 m_GetMesh2URL = config.GetString("Cap_GetMesh2", string.Empty); 113 m_GetMesh2URL = config.GetString("Cap_GetMesh2", string.Empty);
114 if (m_GetMesh2URL != string.Empty) 114 if (m_GetMesh2URL != string.Empty)
115 m_Enabled = true; 115 m_Enabled = true;
116/* 116
117 m_GetAssetURL = config.GetString("Cap_GetAsset", string.Empty); 117 m_GetAssetURL = config.GetString("Cap_GetAsset", string.Empty);
118 if (m_GetAssetURL != string.Empty) 118 if (m_GetAssetURL != string.Empty)
119 m_Enabled = true; 119 m_Enabled = true;
120*/ 120
121 } 121 }
122 122
123 public void AddRegion(Scene pScene) 123 public void AddRegion(Scene pScene)
@@ -204,19 +204,26 @@ namespace OpenSim.Region.ClientStack.Linden
204 204
205 private static void DoAssetRequests() 205 private static void DoAssetRequests()
206 { 206 {
207 while (m_NumberScenes > 0) 207 try
208 { 208 {
209 APollRequest poolreq; 209 while (m_NumberScenes > 0)
210 if(m_queue.TryTake(out poolreq, 4500))
211 { 210 {
212 if (m_NumberScenes <= 0) 211 APollRequest poolreq;
213 break; 212 if (m_queue.TryTake(out poolreq, 4500))
213 {
214 if (m_NumberScenes <= 0)
215 break;
216 Watchdog.UpdateThread();
217 if (poolreq.reqID != UUID.Zero)
218 poolreq.thepoll.Process(poolreq);
219 poolreq = null;
220 }
214 Watchdog.UpdateThread(); 221 Watchdog.UpdateThread();
215 if (poolreq.reqID != UUID.Zero)
216 poolreq.thepoll.Process(poolreq);
217 poolreq = null;
218 } 222 }
219 Watchdog.UpdateThread(); 223 }
224 catch (ThreadAbortException)
225 {
226 Thread.ResetAbort();
220 } 227 }
221 } 228 }
222 229
@@ -441,7 +448,6 @@ namespace OpenSim.Region.ClientStack.Linden
441 else if (m_GetMesh2URL != string.Empty) 448 else if (m_GetMesh2URL != string.Empty)
442 caps.RegisterHandler("GetMesh2", m_GetMesh2URL); 449 caps.RegisterHandler("GetMesh2", m_GetMesh2URL);
443 450
444/* we can't support this cap. Current viewers connect to the wrong regions.
445 //ViewerAsset 451 //ViewerAsset
446 if (m_GetAssetURL == "localhost") 452 if (m_GetAssetURL == "localhost")
447 { 453 {
@@ -459,7 +465,7 @@ namespace OpenSim.Region.ClientStack.Linden
459 } 465 }
460 else if (m_GetAssetURL != string.Empty) 466 else if (m_GetAssetURL != string.Empty)
461 caps.RegisterHandler("ViewerAsset", m_GetMesh2URL); 467 caps.RegisterHandler("ViewerAsset", m_GetMesh2URL);
462*/ 468
463 } 469 }
464 470
465 private void DeregisterCaps(UUID agentID, Caps caps) 471 private void DeregisterCaps(UUID agentID, Caps caps)
@@ -480,13 +486,12 @@ namespace OpenSim.Region.ClientStack.Linden
480 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); 486 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
481 m_capsDictGetMesh2.Remove(agentID); 487 m_capsDictGetMesh2.Remove(agentID);
482 } 488 }
483/* 489
484 if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl)) 490 if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl))
485 { 491 {
486 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); 492 MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl);
487 m_capsDictGetAsset.Remove(agentID); 493 m_capsDictGetAsset.Remove(agentID);
488 } 494 }
489*/
490 } 495 }
491 } 496 }
492} 497}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 41d70a3..9a01567 100644..100755
--- 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
395 395
396 private static void DoInventoryRequests() 396 private static void DoInventoryRequests()
397 { 397 {
398 while (true) 398 bool running = true;
399 while (running)
399 { 400 {
400 APollRequest poolreq; 401 try
401 if (m_queue.TryTake(out poolreq, 4500))
402 { 402 {
403 APollRequest poolreq;
404 if (m_queue.TryTake(out poolreq, 4500))
405 {
406 Watchdog.UpdateThread();
407 if (poolreq.thepoll != null)
408 poolreq.thepoll.Process(poolreq);
409 poolreq = null;
410 }
403 Watchdog.UpdateThread(); 411 Watchdog.UpdateThread();
404 if (poolreq.thepoll != null)
405 poolreq.thepoll.Process(poolreq);
406 poolreq = null;
407 } 412 }
408 Watchdog.UpdateThread(); 413 catch (ThreadAbortException)
414 {
415 Thread.ResetAbort();
416 running = false;
417 }
409 } 418 }
410 } 419 }
411 } 420 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index b7d5a80..ac041f5 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
1257 SendLayerTopRight(x1 + 1, y1, x2, y2 - 1); 1257 SendLayerTopRight(x1 + 1, y1, x2, y2 - 1);
1258 } 1258 }
1259 1259
1260 static private readonly byte[] TerrainPacketHeader = new byte[] {
1261 Helpers.MSG_RELIABLE, // zero code is not as spec
1262 0, 0, 0, 0, // sequence number
1263 0, // extra
1264 11, // ID (high frequency)
1265 };
1266
1267 private const int END_OF_PATCHES = 97;
1268 private const int STRIDE = 264;
1269
1260 public void SendLayerData(int[] map) 1270 public void SendLayerData(int[] map)
1261 { 1271 {
1262 if(map == null) 1272 if(map == null)
@@ -1264,9 +1274,75 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1264 1274
1265 try 1275 try
1266 { 1276 {
1267 List<LayerDataPacket> packets = OpenSimTerrainCompressor.CreateLayerDataPackets(m_scene.Heightmap.GetTerrainData(), map); 1277 TerrainData terrData = m_scene.Heightmap.GetTerrainData();
1268 foreach (LayerDataPacket pkt in packets) 1278 byte landPacketType = (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) ?
1269 OutPacket(pkt, ThrottleOutPacketType.Land); 1279 (byte)TerrainPatch.LayerType.LandExtended : (byte)TerrainPatch.LayerType.Land;
1280
1281 int numberPatchs = map.Length / 2;
1282
1283 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
1284 byte[] data = buf.Data;
1285
1286 Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
1287
1288 data[7] = landPacketType;
1289 //data[8] and data[9] == datablock size to fill later
1290
1291 data[10] = 0; // BitPack needs this on reused packets
1292
1293 // start data
1294 BitPack bitpack = new BitPack(data, 10);
1295 bitpack.PackBits(STRIDE, 16);
1296 bitpack.PackBitsFromByte(16);
1297 bitpack.PackBitsFromByte(landPacketType);
1298
1299 int s;
1300 int datasize = 0;
1301 for (int i = 0; i < numberPatchs; i++)
1302 {
1303 s = 2 * i;
1304 OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]);
1305 if (bitpack.BytePos > 950 && i != numberPatchs - 1)
1306 {
1307 //finish this packet
1308 bitpack.PackBitsFromByte(END_OF_PATCHES);
1309
1310 // fix the datablock lenght
1311 datasize = bitpack.BytePos - 9;
1312 data[8] = (byte)datasize;
1313 data[9] = (byte)(datasize >> 8);
1314
1315 buf.DataLength = bitpack.BytePos + 1;
1316 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
1317
1318 // start another
1319 buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
1320 data = buf.Data;
1321
1322 Buffer.BlockCopy(TerrainPacketHeader, 0, data, 0, 7);
1323
1324 data[7] = landPacketType;
1325 //data[8] and data[9] == datablock size to fill later
1326
1327 data[10] = 0; // BitPack needs this
1328 // start data
1329 bitpack = new BitPack(data, 10);
1330
1331 bitpack.PackBits(STRIDE, 16);
1332 bitpack.PackBitsFromByte(16);
1333 bitpack.PackBitsFromByte(landPacketType);
1334 }
1335 }
1336
1337 bitpack.PackBitsFromByte(END_OF_PATCHES);
1338
1339 datasize = bitpack.BytePos - 9;
1340 data[8] = (byte)datasize;
1341 data[9] = (byte)(datasize >> 8);
1342
1343 buf.DataLength = bitpack.BytePos + 1;
1344 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false);
1345
1270 } 1346 }
1271 catch (Exception e) 1347 catch (Exception e)
1272 { 1348 {
@@ -1677,8 +1753,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1677 1753
1678 public void SendKillObject(List<uint> localIDs) 1754 public void SendKillObject(List<uint> localIDs)
1679 { 1755 {
1680 // foreach (uint id in localIDs) 1756 // foreach (uint id in localIDs)
1681 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); 1757 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1682 1758
1683 // remove pending entities to reduce looping chances. 1759 // remove pending entities to reduce looping chances.
1684 lock (m_entityProps.SyncRoot) 1760 lock (m_entityProps.SyncRoot)
@@ -1702,10 +1778,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1702 1778
1703 if(++nsent >= 200) 1779 if(++nsent >= 200)
1704 { 1780 {
1705 kill.Header.Reliable = true;
1706 kill.Header.Zerocoded = true;
1707 OutPacket(kill, ThrottleOutPacketType.Task); 1781 OutPacket(kill, ThrottleOutPacketType.Task);
1708
1709 perpacket = localIDs.Count - i - 1; 1782 perpacket = localIDs.Count - i - 1;
1710 if(perpacket == 0) 1783 if(perpacket == 0)
1711 break; 1784 break;
@@ -1720,8 +1793,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1720 1793
1721 if(nsent != 0) 1794 if(nsent != 0)
1722 { 1795 {
1723 kill.Header.Reliable = true;
1724 kill.Header.Zerocoded = true;
1725 OutPacket(kill, ThrottleOutPacketType.Task); 1796 OutPacket(kill, ThrottleOutPacketType.Task);
1726 } 1797 }
1727 } 1798 }
@@ -3832,32 +3903,136 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3832 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 3903 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3833 } 3904 }
3834 3905
3906/*
3835 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3907 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3836 { 3908 {
3837// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); 3909// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
3838 3910
3839 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); 3911 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
3840 // TODO: don't create new blocks if recycling an old packet 3912 // TODO: don't create new blocks if recycling an old packet
3841 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[animations.Length];
3842 ani.Sender = new AvatarAnimationPacket.SenderBlock(); 3913 ani.Sender = new AvatarAnimationPacket.SenderBlock();
3843 ani.Sender.ID = sourceAgentId; 3914 ani.Sender.ID = sourceAgentId;
3844 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; 3915 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
3845 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; 3916 ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0];
3846 3917
3847 for (int i = 0; i < animations.Length; ++i) 3918 //self animations
3919 if (sourceAgentId == AgentId)
3848 { 3920 {
3849 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); 3921 List<int> withobjects = new List<int>(animations.Length);
3850 ani.AnimationList[i].AnimID = animations[i]; 3922 List<int> noobjects = new List<int>(animations.Length);
3851 ani.AnimationList[i].AnimSequenceID = seqs[i]; 3923 for(int i = 0; i < animations.Length; ++i)
3924 {
3925 if(objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
3926 noobjects.Add(i);
3927 else
3928 withobjects.Add(i);
3929 }
3852 3930
3853 ani.AnimationSourceList[i] = new AvatarAnimationPacket.AnimationSourceListBlock(); 3931 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[withobjects.Count];
3854 if (objectIDs[i].Equals(sourceAgentId)) 3932 int k = 0;
3855 ani.AnimationSourceList[i].ObjectID = UUID.Zero; 3933 foreach (int i in withobjects)
3856 else 3934 {
3857 ani.AnimationSourceList[i].ObjectID = objectIDs[i]; 3935 ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
3936 ani.AnimationList[k].AnimID = animations[i];
3937 ani.AnimationList[k].AnimSequenceID = seqs[i];
3938 ani.AnimationSourceList[k] = new AvatarAnimationPacket.AnimationSourceListBlock();
3939 ani.AnimationSourceList[k].ObjectID = objectIDs[i];
3940 k++;
3941 }
3942 foreach (int i in noobjects)
3943 {
3944 ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock();
3945 ani.AnimationList[k].AnimID = animations[i];
3946 ani.AnimationList[k].AnimSequenceID = seqs[i];
3947 k++;
3948 }
3949 }
3950 else
3951 {
3952 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[0];
3953 for (int i = 0; i < animations.Length; ++i)
3954 {
3955 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
3956 ani.AnimationList[i].AnimID = animations[i];
3957 ani.AnimationList[i].AnimSequenceID = seqs[i];
3958 }
3858 } 3959 }
3960
3859 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 3961 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3860 } 3962 }
3963*/
3964
3965 static private readonly byte[] AvatarAnimationHeader = new byte[] {
3966 Helpers.MSG_RELIABLE,
3967 0, 0, 0, 0, // sequence number
3968 0, // extra
3969 20 // ID (high frequency)
3970 };
3971
3972 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
3973 {
3974 // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name);
3975
3976 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
3977 byte[] data = buf.Data;
3978 //setup header
3979 Buffer.BlockCopy(AvatarAnimationHeader, 0, data, 0, 7);
3980 //agent block
3981 sourceAgentId.ToBytes(data, 7);
3982
3983 // animations count
3984 data[23] = (byte)animations.Length;
3985
3986 int pos = 24;
3987
3988 //self animations
3989 if (sourceAgentId == AgentId)
3990 {
3991 List<int> withobjects = new List<int>(animations.Length);
3992 List<int> noobjects = new List<int>(animations.Length);
3993 for (int i = 0; i < animations.Length; ++i)
3994 {
3995 if (objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero)
3996 noobjects.Add(i);
3997 else
3998 withobjects.Add(i);
3999 }
4000
4001 // first the ones with corresponding objects
4002 foreach (int i in withobjects)
4003 {
4004 animations[i].ToBytes(data, pos); pos += 16;
4005 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4006 }
4007 // then the rest
4008 foreach (int i in noobjects)
4009 {
4010 animations[i].ToBytes(data, pos); pos += 16;
4011 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4012 }
4013 // object ids block
4014 data[pos++] = (byte)withobjects.Count;
4015 foreach (int i in withobjects)
4016 {
4017 objectIDs[i].ToBytes(data, pos); pos += 16;
4018 }
4019 }
4020 else
4021 {
4022 for(int i = 0; i < animations.Length; ++i)
4023 {
4024 animations[i].ToBytes(data, pos); pos += 16;
4025 Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4;
4026 }
4027 data[pos++] = 0; // no object ids
4028 }
4029
4030 data[pos++] = 0; // no physical avatar events
4031
4032 buf.DataLength = pos;
4033 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority,
4034 null, false, false);
4035 }
3861 4036
3862 public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId) 4037 public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId)
3863 { 4038 {
@@ -3889,36 +4064,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3889 /// </summary> 4064 /// </summary>
3890 public void SendEntityFullUpdateImmediate(ISceneEntity ent) 4065 public void SendEntityFullUpdateImmediate(ISceneEntity ent)
3891 { 4066 {
3892// m_log.DebugFormat( 4067 if (ent == null || (!(ent is ScenePresence) && !(ent is SceneObjectPart)))
3893// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}",
3894// avatar.Name, avatar.UUID, Name, AgentId);
3895
3896 if (ent == null)
3897 return; 4068 return;
3898 4069
3899 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 4070 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
3900 objupdate.Header.Zerocoded = true; 4071 Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
3901 4072
3902 objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 4073 LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
3903 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 4074 zc.Position = 7;
3904 4075
3905 if(ent is ScenePresence) 4076 zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
3906 { 4077 zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
3907 ScenePresence presence = ent as ScenePresence; 4078
3908 objupdate.RegionData.RegionHandle = presence.RegionHandle; 4079 zc.AddByte(1); // block count
3909 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 4080
3910 } 4081 ThrottleOutPacketType ptype = ThrottleOutPacketType.Task;
3911 else if(ent is SceneObjectPart) 4082 if (ent is ScenePresence)
3912 { 4083 {
3913 SceneObjectPart part = ent as SceneObjectPart; 4084 CreateAvatarUpdateBlock(ent as ScenePresence, zc);
3914 objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4085 ptype |= ThrottleOutPacketType.HighPriority;
3915 objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent);
3916 } 4086 }
4087 else
4088 CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc);
3917 4089
3918 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); 4090 buf.DataLength = zc.Finish();
3919 4091 m_udpServer.SendUDPPacket(m_udpClient, buf, ptype , null, false, false);
3920 // We need to record the avatar local id since the root prim of an attachment points to this.
3921// m_attachmentsSent.Add(avatar.LocalId);
3922 } 4092 }
3923 4093
3924 public void SendEntityTerseUpdateImmediate(ISceneEntity ent) 4094 public void SendEntityTerseUpdateImmediate(ISceneEntity ent)
@@ -4089,6 +4259,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4089 ResendPrimUpdate(update); 4259 ResendPrimUpdate(update);
4090 } 4260 }
4091 4261
4262 static private readonly byte[] objectUpdateHeader = new byte[] {
4263 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED,
4264 0, 0, 0, 0, // sequence number
4265 0, // extra
4266 12 // ID (high frequency)
4267 };
4268
4269 static private readonly byte[] terseUpdateHeader = new byte[] {
4270 Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, // zero code is not as spec
4271 0, 0, 0, 0, // sequence number
4272 0, // extra
4273 15 // ID (high frequency)
4274 };
4275
4092 private void ProcessEntityUpdates(int maxUpdatesBytes) 4276 private void ProcessEntityUpdates(int maxUpdatesBytes)
4093 { 4277 {
4094 if (!IsActive) 4278 if (!IsActive)
@@ -4098,14 +4282,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4098 if (mysp == null) 4282 if (mysp == null)
4099 return; 4283 return;
4100 4284
4101 List<ObjectUpdatePacket.ObjectDataBlock> objectUpdateBlocks = null; 4285 // List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null;
4102 List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null;
4103 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseUpdateBlocks = null;
4104 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> terseAgentUpdateBlocks = null;
4105 List<EntityUpdate> objectUpdates = null; 4286 List<EntityUpdate> objectUpdates = null;
4106 List<EntityUpdate> compressedUpdates = null; 4287 // List<EntityUpdate> compressedUpdates = null;
4107 List<EntityUpdate> terseUpdates = null; 4288 List<EntityUpdate> terseUpdates = null;
4108 List<EntityUpdate> terseAgentUpdates = null;
4109 List<SceneObjectPart> ObjectAnimationUpdates = null; 4289 List<SceneObjectPart> ObjectAnimationUpdates = null;
4110 4290
4111 // Check to see if this is a flush 4291 // Check to see if this is a flush
@@ -4120,10 +4300,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4120 float cullingrange = 64.0f; 4300 float cullingrange = 64.0f;
4121 Vector3 mypos = Vector3.Zero; 4301 Vector3 mypos = Vector3.Zero;
4122 4302
4123 bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; 4303 //bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance;
4304 bool orderedDequeue = false; // temporary off
4124 4305
4125 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>(); 4306 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>();
4126 4307
4308
4127 if (doCulling) 4309 if (doCulling)
4128 { 4310 {
4129 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; 4311 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f;
@@ -4179,7 +4361,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4179 } 4361 }
4180 4362
4181 if (grp.IsAttachment) 4363 if (grp.IsAttachment)
4182 { // Someone else's HUD, why are we getting these? 4364 {
4365 // animated attachments are nasty if not supported by viewer
4366 if(!m_SupportObjectAnimations && grp.RootPart.Shape.MeshFlagEntry)
4367 continue;
4368
4369 // Someone else's HUD, why are we getting these?
4183 if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint) 4370 if (grp.OwnerID != AgentId && grp.HasPrivateAttachmentPoint)
4184 continue; 4371 continue;
4185 4372
@@ -4273,7 +4460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4273 if(ObjectAnimationUpdates == null) 4460 if(ObjectAnimationUpdates == null)
4274 ObjectAnimationUpdates = new List<SceneObjectPart>(); 4461 ObjectAnimationUpdates = new List<SceneObjectPart>();
4275 ObjectAnimationUpdates.Add(sop); 4462 ObjectAnimationUpdates.Add(sop);
4276 maxUpdatesBytes -= 32 * sop.Animations.Count + 16; 4463 maxUpdatesBytes -= 20 * sop.Animations.Count + 24;
4277 } 4464 }
4278 } 4465 }
4279 } 4466 }
@@ -4304,7 +4491,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4304 PrimUpdateFlags.Velocity | 4491 PrimUpdateFlags.Velocity |
4305 PrimUpdateFlags.Acceleration | 4492 PrimUpdateFlags.Acceleration |
4306 PrimUpdateFlags.AngularVelocity | 4493 PrimUpdateFlags.AngularVelocity |
4307 PrimUpdateFlags.CollisionPlane 4494 PrimUpdateFlags.CollisionPlane |
4495 PrimUpdateFlags.Textures
4308 ); 4496 );
4309 4497
4310 #endregion UpdateFlags to packet type conversion 4498 #endregion UpdateFlags to packet type conversion
@@ -4326,48 +4514,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4326 4514
4327 if ((updateFlags & canNotUseImprovedMask) == 0) 4515 if ((updateFlags & canNotUseImprovedMask) == 0)
4328 { 4516 {
4329 ImprovedTerseObjectUpdatePacket.ObjectDataBlock ablock = 4517 if (terseUpdates == null)
4330 CreateImprovedTerseBlock(update.Entity);
4331
4332 if (update.Entity is ScenePresence)
4333 { 4518 {
4334 // ALL presence updates go into a special list 4519 terseUpdates = new List<EntityUpdate>();
4335 if (terseAgentUpdateBlocks == null) 4520 maxUpdatesBytes -= 18;
4336 {
4337 terseAgentUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4338 terseAgentUpdates = new List<EntityUpdate>();
4339 }
4340 terseAgentUpdateBlocks.Add(ablock);
4341 terseAgentUpdates.Add(update);
4342 } 4521 }
4522 terseUpdates.Add(update);
4523
4524 if (update.Entity is ScenePresence)
4525 maxUpdatesBytes -= 63; // no texture entry
4343 else 4526 else
4344 { 4527 {
4345 // Everything else goes here 4528 if ((updateFlags & PrimUpdateFlags.Textures) == 0)
4346 if (terseUpdateBlocks == null) 4529 maxUpdatesBytes -= 47;
4347 { 4530 else
4348 terseUpdateBlocks = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 4531 maxUpdatesBytes -= 150; // aprox
4349 terseUpdates = new List<EntityUpdate>();
4350 }
4351 terseUpdateBlocks.Add(ablock);
4352 terseUpdates.Add(update);
4353 } 4532 }
4354 maxUpdatesBytes -= ablock.Length;
4355 } 4533 }
4356 else 4534 else
4357 { 4535 {
4358 ObjectUpdatePacket.ObjectDataBlock ablock;
4359 if (update.Entity is ScenePresence) 4536 if (update.Entity is ScenePresence)
4360 ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); 4537 maxUpdatesBytes -= 150; // crude estimation
4361 else 4538 else
4362 ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); 4539 maxUpdatesBytes -= 300;
4363 if(objectUpdateBlocks == null) 4540
4541 if(objectUpdates == null)
4364 { 4542 {
4365 objectUpdateBlocks = new List<ObjectUpdatePacket.ObjectDataBlock>();
4366 objectUpdates = new List<EntityUpdate>(); 4543 objectUpdates = new List<EntityUpdate>();
4544 maxUpdatesBytes -= 18;
4367 } 4545 }
4368 objectUpdateBlocks.Add(ablock);
4369 objectUpdates.Add(update); 4546 objectUpdates.Add(update);
4370 maxUpdatesBytes -= ablock.Length;
4371 } 4547 }
4372 4548
4373 #endregion Block Construction 4549 #endregion Block Construction
@@ -4382,29 +4558,87 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4382 4558
4383 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 4559 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4384 4560
4385 if (terseAgentUpdateBlocks != null) 4561 if(objectUpdates != null)
4386 { 4562 {
4387 ImprovedTerseObjectUpdatePacket packet 4563 int blocks = objectUpdates.Count;
4388 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4564 List<EntityUpdate> tau = new List<EntityUpdate>(30);
4389 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4390 packet.RegionData.TimeDilation = timeDilation;
4391 packet.ObjectData = terseAgentUpdateBlocks.ToArray();
4392 terseAgentUpdateBlocks.Clear();
4393 4565
4394 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates, oPacket); }); 4566 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4395 } 4567 Buffer.BlockCopy(objectUpdateHeader, 0, buf.Data, 0, 7);
4396 4568
4397 if (objectUpdateBlocks != null) 4569 LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
4398 { 4570 zc.Position = 7;
4399 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 4571
4400 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4572 zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
4401 packet.RegionData.TimeDilation = timeDilation; 4573 zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f));
4402 packet.ObjectData = objectUpdateBlocks.ToArray(); 4574
4403 objectUpdateBlocks.Clear(); 4575 zc.AddByte(1); // tmp block count
4576
4577 int countposition = zc.Position - 1;
4578
4579 int lastpos = 0;
4580 int lastzc = 0;
4581
4582 int count = 0;
4583 foreach (EntityUpdate eu in objectUpdates)
4584 {
4585 lastpos = zc.Position;
4586 lastzc = zc.ZeroCount;
4587 if (eu.Entity is ScenePresence)
4588 CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
4589 else
4590 CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
4591 if (zc.Position < LLUDPServer.MAXPAYLOAD)
4592 {
4593 tau.Add(eu);
4594 ++count;
4595 --blocks;
4596 }
4597 else if (blocks > 0)
4598 {
4599 // we need more packets
4600 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4601 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
4404 4602
4405 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates, oPacket); }); 4603 buf.Data[countposition] = (byte)count;
4604 // get pending zeros at cut point
4605 if(lastzc > 0)
4606 {
4607 buf.Data[lastpos++] = 0;
4608 buf.Data[lastpos++] = (byte)lastzc;
4609 }
4610 buf.DataLength = lastpos;
4611
4612 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4613 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
4614
4615 buf = newbuf;
4616 zc.Data = buf.Data;
4617 zc.ZeroCount = 0;
4618 zc.Position = countposition + 1;
4619 // im lazy now, just do last again
4620 if (eu.Entity is ScenePresence)
4621 CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc);
4622 else
4623 CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc);
4624
4625 tau = new List<EntityUpdate>(30);
4626 tau.Add(eu);
4627 count = 1;
4628 --blocks;
4629 }
4630 }
4631
4632 if (count > 0)
4633 {
4634 buf.Data[countposition] = (byte)count;
4635 buf.DataLength = zc.Finish();
4636 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4637 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
4638 }
4406 } 4639 }
4407 4640
4641/*
4408 if (compressedUpdateBlocks != null) 4642 if (compressedUpdateBlocks != null)
4409 { 4643 {
4410 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); 4644 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
@@ -4415,20 +4649,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4415 4649
4416 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); }); 4650 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); });
4417 } 4651 }
4418 4652*/
4419 if (terseUpdateBlocks != null) 4653 if (terseUpdates != null)
4420 { 4654 {
4421 ImprovedTerseObjectUpdatePacket packet = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 4655 int blocks = terseUpdates.Count;
4422 PacketType.ImprovedTerseObjectUpdate); 4656 List<EntityUpdate> tau = new List<EntityUpdate>(30);
4423 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4657
4424 packet.RegionData.TimeDilation = timeDilation; 4658 UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4425 packet.ObjectData = terseUpdateBlocks.ToArray(); 4659
4426 terseUpdateBlocks.Clear(); 4660 //setup header and regioninfo block
4661 Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7);
4662 Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7);
4663 Utils.UInt16ToBytes(timeDilation, buf.Data, 15);
4664 int pos = 18;
4665 int lastpos = 0;
4427 4666
4428 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates, oPacket); }); 4667 int count = 0;
4668 foreach (EntityUpdate eu in terseUpdates)
4669 {
4670 lastpos = pos;
4671 CreateImprovedTerseBlock(eu.Entity, buf.Data, ref pos, (eu.Flags & PrimUpdateFlags.Textures) != 0);
4672 if (pos < LLUDPServer.MAXPAYLOAD)
4673 {
4674 tau.Add(eu);
4675 ++count;
4676 --blocks;
4677 }
4678 else if (blocks > 0)
4679 {
4680 // we need more packets
4681 UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
4682 Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, 17); // start is the same
4683 // copy what we done in excess
4684 int extralen = pos - lastpos;
4685 if(extralen > 0)
4686 Buffer.BlockCopy(buf.Data, lastpos, newbuf.Data, 18, extralen);
4687
4688 pos = 18 + extralen;
4689
4690 buf.Data[17] = (byte)count;
4691 buf.DataLength = lastpos;
4692 // zero encode is not as spec
4693 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4694 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4695
4696 tau = new List<EntityUpdate>(30);
4697 tau.Add(eu);
4698 count = 1;
4699 --blocks;
4700 buf = newbuf;
4701 }
4702 }
4703
4704 if (count > 0)
4705 {
4706 buf.Data[17] = (byte)count;
4707 buf.DataLength = pos;
4708 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
4709 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
4710 }
4429 } 4711 }
4430 4712
4431 if(ObjectAnimationUpdates != null) 4713 if (ObjectAnimationUpdates != null)
4432 { 4714 {
4433 foreach (SceneObjectPart sop in ObjectAnimationUpdates) 4715 foreach (SceneObjectPart sop in ObjectAnimationUpdates)
4434 { 4716 {
@@ -4445,13 +4727,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4445 UUID[] ids = null; 4727 UUID[] ids = null;
4446 int[] seqs = null; 4728 int[] seqs = null;
4447 int count = sop.GetAnimations(out ids, out seqs); 4729 int count = sop.GetAnimations(out ids, out seqs);
4448 if(count < 0)
4449 continue;
4450 4730
4451 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); 4731 ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation);
4452 ani.Sender = new ObjectAnimationPacket.SenderBlock(); 4732 ani.Sender = new ObjectAnimationPacket.SenderBlock();
4453 ani.Sender.ID = sop.UUID; 4733 ani.Sender.ID = sop.UUID;
4454 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count]; 4734 ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count];
4455 4735
4456 for(int i = 0; i< count; i++) 4736 for(int i = 0; i< count; i++)
4457 { 4737 {
@@ -4642,9 +4922,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4642 // These are used to implement an adaptive backoff in the number 4922 // These are used to implement an adaptive backoff in the number
4643 // of updates converted to packets. Since we don't want packets 4923 // of updates converted to packets. Since we don't want packets
4644 // to sit in the queue with old data, only convert enough updates 4924 // to sit in the queue with old data, only convert enough updates
4645 // to packets that can be sent in 200ms. 4925 // to packets that can be sent in 30ms.
4646// private Int32 m_LastQueueFill = 0;
4647// private Int32 m_maxUpdates = 0;
4648 4926
4649 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 4927 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
4650 { 4928 {
@@ -5645,9 +5923,144 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5645 return block; 5923 return block;
5646 } 5924 }
5647 5925
5926 protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture)
5927 {
5928 #region ScenePresence/SOP Handling
5929
5930 bool avatar = (entity is ScenePresence);
5931 uint localID = entity.LocalId;
5932 uint attachPoint;
5933 Vector4 collisionPlane;
5934 Vector3 position, velocity, acceleration, angularVelocity;
5935 Quaternion rotation;
5936 byte datasize;
5937 byte[] te = null;
5938
5939 if (avatar)
5940 {
5941 ScenePresence presence = (ScenePresence)entity;
5942
5943 position = presence.OffsetPosition;
5944 velocity = presence.Velocity;
5945 acceleration = Vector3.Zero;
5946 rotation = presence.Rotation;
5947 // tpvs can only see rotations around Z in some cases
5948 if (!presence.Flying && !presence.IsSatOnObject)
5949 {
5950 rotation.X = 0f;
5951 rotation.Y = 0f;
5952 }
5953 rotation.Normalize();
5954 angularVelocity = presence.AngularVelocity;
5955
5956 // m_log.DebugFormat(
5957 // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5958
5959 attachPoint = presence.State;
5960 collisionPlane = presence.CollisionPlane;
5961
5962 datasize = 60;
5963 }
5964 else
5965 {
5966 SceneObjectPart part = (SceneObjectPart)entity;
5967
5968 attachPoint = part.ParentGroup.AttachmentPoint;
5969 attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
5970 // m_log.DebugFormat(
5971 // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
5972 // attachPoint, part.Name, part.LocalId, Name);
5973
5974 collisionPlane = Vector4.Zero;
5975 position = part.RelativePosition;
5976 velocity = part.Velocity;
5977 acceleration = part.Acceleration;
5978 angularVelocity = part.AngularVelocity;
5979 rotation = part.RotationOffset;
5980
5981 datasize = 44;
5982 if(includeTexture)
5983 te = part.Shape.TextureEntry;
5984 }
5985
5986 #endregion ScenePresence/SOP Handling
5987 //object block size
5988 data[pos++] = datasize;
5989
5990 // LocalID
5991 Utils.UIntToBytes(localID, data, pos);
5992 pos += 4;
5993
5994 data[pos++] = (byte)attachPoint;
5995
5996 // Avatar/CollisionPlane
5997 if (avatar)
5998 {
5999 data[pos++] = 1;
6000
6001 if (collisionPlane == Vector4.Zero)
6002 collisionPlane = Vector4.UnitW;
6003 //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane);
6004 collisionPlane.ToBytes(data, pos);
6005 pos += 16;
6006 }
6007 else
6008 {
6009 data[pos++] = 0;
6010 }
6011
6012 // Position
6013 position.ToBytes(data, pos);
6014 pos += 12;
6015
6016 // Velocity
6017 ClampVectorForUint(ref velocity, 128f);
6018 Utils.FloatToUInt16Bytes(velocity.X, 128.0f, data, pos); pos += 2;
6019 Utils.FloatToUInt16Bytes(velocity.Y, 128.0f, data, pos); pos += 2;
6020 Utils.FloatToUInt16Bytes(velocity.Z, 128.0f, data, pos); pos += 2;
6021
6022 // Acceleration
6023 ClampVectorForUint(ref acceleration, 64f);
6024 Utils.FloatToUInt16Bytes(acceleration.X, 64.0f, data, pos); pos += 2;
6025 Utils.FloatToUInt16Bytes(acceleration.Y, 64.0f, data, pos); pos += 2;
6026 Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2;
6027
6028 // Rotation
6029 Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2;
6030 Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2;
6031 Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2;
6032 Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2;
6033
6034 // Angular Velocity
6035 ClampVectorForUint(ref angularVelocity, 64f);
6036 Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2;
6037 Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2;
6038 Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2;
6039
6040 // texture entry block size
6041 if(te == null)
6042 {
6043 data[pos++] = 0;
6044 data[pos++] = 0;
6045 }
6046 else
6047 {
6048 int len = te.Length & 0x7fff;
6049 int totlen = len + 4;
6050 data[pos++] = (byte)totlen;
6051 data[pos++] = (byte)(totlen >> 8);
6052 data[pos++] = (byte)len; // wtf ???
6053 data[pos++] = (byte)(len >> 8);
6054 data[pos++] = 0;
6055 data[pos++] = 0;
6056 Buffer.BlockCopy(te, 0, data, pos, len);
6057 pos += len;
6058 }
6059 // total size 63 or 47 + (texture size + 4)
6060 }
6061
5648 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 6062 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5649 { 6063 {
5650 Vector3 offsetPosition = data.OffsetPosition;
5651 Quaternion rotation = data.Rotation; 6064 Quaternion rotation = data.Rotation;
5652 // tpvs can only see rotations around Z in some cases 6065 // tpvs can only see rotations around Z in some cases
5653 if(!data.Flying && !data.IsSatOnObject) 6066 if(!data.Flying && !data.IsSatOnObject)
@@ -5657,27 +6070,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5657 } 6070 }
5658 rotation.Normalize(); 6071 rotation.Normalize();
5659 6072
5660 uint parentID = data.ParentID;
5661
5662// m_log.DebugFormat( 6073// m_log.DebugFormat(
5663// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); 6074// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
5664 6075
5665 byte[] objectData = new byte[76]; 6076 byte[] objectData = new byte[76];
5666 6077
5667 Vector3 velocity = new Vector3(0, 0, 0); 6078 //Vector3 velocity = Vector3.Zero;
5668 Vector3 acceleration = new Vector3(0, 0, 0); 6079 Vector3 acceleration = Vector3.Zero;
6080 Vector3 angularvelocity = Vector3.Zero;
5669 6081
5670 data.CollisionPlane.ToBytes(objectData, 0); 6082 data.CollisionPlane.ToBytes(objectData, 0);
5671 offsetPosition.ToBytes(objectData, 16); 6083 data.OffsetPosition.ToBytes(objectData, 16);
5672 velocity.ToBytes(objectData, 28); 6084 data.Velocity.ToBytes(objectData, 28);
5673 acceleration.ToBytes(objectData, 40); 6085 acceleration.ToBytes(objectData, 40);
5674 rotation.ToBytes(objectData, 52); 6086 rotation.ToBytes(objectData, 52);
5675 data.AngularVelocity.ToBytes(objectData, 64); 6087 angularvelocity.ToBytes(objectData, 64);
5676 6088
5677 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 6089 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5678 6090
5679 update.Data = Utils.EmptyBytes; 6091 update.Data = Utils.EmptyBytes;
5680 update.ExtraParams = new byte[1]; 6092 update.ExtraParams = Utils.EmptyBytes;
5681 update.FullID = data.UUID; 6093 update.FullID = data.UUID;
5682 update.ID = data.LocalId; 6094 update.ID = data.LocalId;
5683 update.Material = (byte)Material.Flesh; 6095 update.Material = (byte)Material.Flesh;
@@ -5714,7 +6126,158 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5714 return update; 6126 return update;
5715 } 6127 }
5716 6128
5717// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) 6129 protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos)
6130 {
6131 Quaternion rotation = data.Rotation;
6132 // tpvs can only see rotations around Z in some cases
6133 if (!data.Flying && !data.IsSatOnObject)
6134 {
6135 rotation.X = 0f;
6136 rotation.Y = 0f;
6137 }
6138 rotation.Normalize();
6139
6140 //Vector3 velocity = Vector3.Zero;
6141 //Vector3 acceleration = Vector3.Zero;
6142 //Vector3 angularvelocity = Vector3.Zero;
6143
6144 Utils.UIntToBytesSafepos(data.LocalId, dest, pos); pos += 4;
6145 dest[pos++] = 0; // state
6146 data.UUID.ToBytes(dest, pos); pos += 16;
6147 Utils.UIntToBytesSafepos(0 , dest, pos); pos += 4; // crc
6148 dest[pos++] = (byte)PCode.Avatar;
6149 dest[pos++] = (byte)Material.Flesh;
6150 dest[pos++] = 0; // clickaction
6151 data.Appearance.AvatarSize.ToBytes(dest, pos); pos += 12;
6152
6153 // objectdata block
6154 dest[pos++] = 76;
6155 data.CollisionPlane.ToBytes(dest, pos); pos += 16;
6156 data.OffsetPosition.ToBytes(dest, pos); pos += 12;
6157 data.Velocity.ToBytes(dest, pos); pos += 12;
6158
6159 //acceleration.ToBytes(dest, pos); pos += 12;
6160 Array.Clear(dest, pos, 12); pos += 12;
6161
6162 rotation.ToBytes(dest, pos); pos += 12;
6163
6164 //angularvelocity.ToBytes(dest, pos); pos += 12;
6165 Array.Clear(dest, pos, 12); pos += 12;
6166
6167 SceneObjectPart parentPart = data.ParentPart;
6168 if (parentPart != null)
6169 {
6170 Utils.UIntToBytesSafepos(parentPart.ParentGroup.LocalId, dest, pos);
6171 pos += 4;
6172 }
6173 else
6174 {
6175// Utils.UIntToBytesSafepos(0, dest, pos);
6176// pos += 4;
6177 dest[pos++] = 0;
6178 dest[pos++] = 0;
6179 dest[pos++] = 0;
6180 dest[pos++] = 0;
6181 }
6182
6183 //Utils.UIntToBytesSafepos(0, dest, pos); pos += 4; //update flags
6184 dest[pos++] = 0;
6185 dest[pos++] = 0;
6186 dest[pos++] = 0;
6187 dest[pos++] = 0;
6188
6189 //pbs
6190 dest[pos++] = 16;
6191 dest[pos++] = 1;
6192 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
6193 //Utils.UInt16ToBytes(0, dest, pos); pos += 2;
6194 dest[pos++] = 0;
6195 dest[pos++] = 0;
6196 dest[pos++] = 0;
6197 dest[pos++] = 0;
6198
6199 dest[pos++] = 100;
6200 dest[pos++] = 100;
6201
6202 // rest of pbs is 0 (15), texture entry (2) and texture anim (1)
6203 const int pbszeros = 15 + 2 + 1;
6204 Array.Clear(dest, pos, pbszeros); pos += pbszeros;
6205
6206 //NameValue
6207 byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
6208 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
6209 int len = nv.Length;
6210 dest[pos++] = (byte)len;
6211 dest[pos++] = (byte)(len >> 8);
6212 Buffer.BlockCopy(nv, 0, dest, pos, len); pos += len;
6213
6214 // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
6215 // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
6216 // jointtype(1) joint pivot(12) joint offset(12)
6217 const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
6218 Array.Clear(dest, pos, lastzeros); pos += lastzeros;
6219 }
6220
6221 protected void CreateAvatarUpdateBlock(ScenePresence data, LLUDPZeroEncoder zc)
6222 {
6223 Quaternion rotation = data.Rotation;
6224 // tpvs can only see rotations around Z in some cases
6225 if (!data.Flying && !data.IsSatOnObject)
6226 {
6227 rotation.X = 0f;
6228 rotation.Y = 0f;
6229 }
6230 rotation.Normalize();
6231
6232 zc.AddUInt(data.LocalId);
6233 zc.AddByte(0);
6234 zc.AddUUID(data.UUID);
6235 zc.AddZeros(4); // crc unused
6236 zc.AddByte((byte)PCode.Avatar);
6237 zc.AddByte((byte)Material.Flesh);
6238 zc.AddByte(0); // clickaction
6239 zc.AddVector3(data.Appearance.AvatarSize);
6240
6241 // objectdata block
6242 zc.AddByte(76); // fixed avatar block size
6243 zc.AddVector4(data.CollisionPlane);
6244 zc.AddVector3(data.OffsetPosition);
6245 zc.AddVector3(data.Velocity);
6246 //zc.AddVector3(acceleration);
6247 zc.AddZeros(12);
6248 zc.AddNormQuat(rotation);
6249 //zc.AddVector3(angularvelocity);
6250 zc.AddZeros(12);
6251
6252 SceneObjectPart parentPart = data.ParentPart;
6253 if (parentPart != null)
6254 zc.AddUInt(parentPart.ParentGroup.LocalId);
6255 else
6256 zc.AddZeros(4);
6257
6258 zc.AddZeros(4); //update flags
6259
6260 //pbs volume data 23
6261 //texture entry 2
6262 //texture anim (1)
6263 const int pbszeros = 23 + 2 + 1;
6264 zc.AddZeros(pbszeros);
6265
6266 //NameValue
6267 byte[] nv = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
6268 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
6269 int len = nv.Length;
6270 zc.AddByte((byte)len);
6271 zc.AddByte((byte)(len >> 8));
6272 zc.AddBytes(nv, len);
6273
6274 // data(2), text(1), text color(4), media url(1), PBblock(1), ExtramParams(1),
6275 // sound id(16), sound owner(16) gain (4), flags (1), radius (4)
6276 // jointtype(1) joint pivot(12) joint offset(12)
6277 const int lastzeros = 2 + 1 + 4 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12;
6278 zc.AddZeros(lastzeros);
6279 }
6280
5718 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) 6281 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp)
5719 { 6282 {
5720 byte[] objectData = new byte[60]; 6283 byte[] objectData = new byte[60];
@@ -5737,32 +6300,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5737 //update.JointPivot = Vector3.Zero; 6300 //update.JointPivot = Vector3.Zero;
5738 //update.JointType = 0; 6301 //update.JointType = 0;
5739 update.Material = part.Material; 6302 update.Material = part.Material;
5740/*
5741 if (data.ParentGroup.IsAttachment)
5742 {
5743 update.NameValue
5744 = Util.StringToBytes256(
5745 string.Format("AttachItemID STRING RW SV {0}", data.ParentGroup.FromItemID));
5746
5747 update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16));
5748
5749// m_log.DebugFormat(
5750// "[LLCLIENTVIEW]: Sending NameValue {0} for {1} {2} to {3}",
5751// Util.UTF8.GetString(update.NameValue), data.Name, data.LocalId, Name);
5752//
5753// m_log.DebugFormat(
5754// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}",
5755// update.State, data.Name, data.LocalId, Name);
5756 }
5757 else
5758 {
5759 update.NameValue = Utils.EmptyBytes;
5760
5761 // The root part state is the canonical state for all parts of the object. The other part states in the
5762 // case for attachments may contain conflicting values that can end up crashing the viewer.
5763 update.State = data.ParentGroup.RootPart.Shape.State;
5764 }
5765*/
5766 6303
5767 if (part.ParentGroup.IsAttachment) 6304 if (part.ParentGroup.IsAttachment)
5768 { 6305 {
@@ -5858,15 +6395,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5858 6395
5859 #endregion PrimFlags 6396 #endregion PrimFlags
5860 6397
5861 if (part.Sound != UUID.Zero || part.SoundFlags != 0) 6398 bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
6399 if (hassound)
5862 { 6400 {
5863 update.Sound = part.Sound; 6401 update.Sound = part.Sound;
5864 update.OwnerID = part.OwnerID;
5865 update.Gain = (float)part.SoundGain; 6402 update.Gain = (float)part.SoundGain;
5866 update.Radius = (float)part.SoundRadius; 6403 update.Radius = (float)part.SoundRadius;
5867 update.Flags = part.SoundFlags; 6404 update.Flags = part.SoundFlags;
5868 } 6405 }
5869 6406
6407 if(hassound || update.PSBlock.Length > 1)
6408 update.OwnerID = part.OwnerID;
6409
5870 switch ((PCode)part.Shape.PCode) 6410 switch ((PCode)part.Shape.PCode)
5871 { 6411 {
5872 case PCode.Grass: 6412 case PCode.Grass:
@@ -5882,6 +6422,308 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5882 return update; 6422 return update;
5883 } 6423 }
5884 6424
6425 protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc)
6426 {
6427 // prepare data
6428
6429 #region PrimFlags
6430 // prim/update flags
6431 PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
6432 // Don't send the CreateSelected flag to everyone
6433 primflags &= ~PrimFlags.CreateSelected;
6434 if (sp.UUID == part.OwnerID)
6435 {
6436 if (part.CreateSelected)
6437 {
6438 // Only send this flag once, then unset it
6439 primflags |= PrimFlags.CreateSelected;
6440 part.CreateSelected = false;
6441 }
6442 }
6443 #endregion PrimFlags
6444
6445 // data block
6446 byte[] data = null;
6447 byte state = part.Shape.State;
6448 PCode pcode = (PCode)part.Shape.PCode;
6449
6450 //vegetation is special so just do it inline
6451 if(pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
6452 {
6453 zc.AddUInt(part.LocalId);
6454 zc.AddByte(state); // state
6455 zc.AddUUID(part.UUID);
6456 zc.AddZeros(4); // crc unused
6457 zc.AddByte((byte)pcode);
6458 // material 1
6459 // clickaction 1
6460 zc.AddZeros(2);
6461 zc.AddVector3(part.Shape.Scale);
6462
6463 // objectdata block
6464 zc.AddByte(60); // fixed object block size
6465 zc.AddVector3(part.RelativePosition);
6466 if (pcode == PCode.Grass)
6467 zc.AddZeros(48);
6468 else
6469 {
6470 zc.AddZeros(24);
6471 Quaternion rot = part.RotationOffset;
6472 rot.Normalize();
6473 zc.AddNormQuat(rot);
6474 zc.AddZeros(12);
6475 }
6476
6477 zc.AddUInt(part.ParentID);
6478 zc.AddUInt((uint)primflags); //update flags
6479
6480 /*
6481 if (pcode == PCode.Grass)
6482 {
6483 //pbs volume data 23
6484 //texture entry 2
6485 //texture anim 1
6486 //name value 2
6487 // data 1
6488 // text 5
6489 // media url 1
6490 // particle system 1
6491 // Extraparams 1
6492 // sound id 16
6493 // ownwer 16
6494 // sound gain 4
6495 // sound flags 1
6496 // sound radius 4
6497 // jointtype 1
6498 // joint pivot 12
6499 // joint offset 12
6500 zc.AddZeros(23 + 2 + 1 + 2 + 1 + 5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
6501 return;
6502 }
6503 */
6504
6505 //pbs volume data 23
6506 //texture entry 2
6507 //texture anim 1
6508 //name value 2
6509 zc.AddZeros(23 + 2 + 1 + 2);
6510
6511 //data: the tree type
6512 zc.AddByte(1);
6513 zc.AddZeros(1);
6514 zc.AddByte(state);
6515
6516 // text 5
6517 // media url 1
6518 // particle system 1
6519 // Extraparams 1
6520 // sound id 16
6521 // ownwer 16
6522 // sound gain 4
6523 // sound flags 1
6524 // sound radius 4
6525 // jointtype 1
6526 // joint pivot 12
6527 // joint offset 12
6528 zc.AddZeros(5 + 1 + 1 + 1 + 16 + 16 + 4 + 1 + 4 + 1 + 12 + 12);
6529
6530 return;
6531 }
6532
6533 //NameValue and state
6534 byte[] nv = null;
6535
6536 if (part.ParentGroup.IsAttachment)
6537 {
6538 if (part.IsRoot)
6539 nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID);
6540
6541 int st = (int)part.ParentGroup.AttachmentPoint;
6542 state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
6543 }
6544
6545 // filter out mesh faces hack
6546 ushort profileBegin = part.Shape.ProfileBegin;
6547 ushort profileHollow = part.Shape.ProfileHollow;
6548 byte profileCurve = part.Shape.ProfileCurve;
6549 byte pathScaleY = part.Shape.PathScaleY;
6550
6551 if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
6552 {
6553 profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
6554 // fix old values that confused viewers
6555 if (profileBegin == 1)
6556 profileBegin = 9375;
6557 if (profileHollow == 1)
6558 profileHollow = 27500;
6559 // fix torus hole size Y that also confuse some viewers
6560 if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
6561 pathScaleY = 150;
6562 }
6563
6564 // do encode the things
6565 zc.AddUInt(part.LocalId);
6566 zc.AddByte(state); // state
6567 zc.AddUUID(part.UUID);
6568 zc.AddZeros(4); // crc unused
6569 zc.AddByte((byte)pcode);
6570 zc.AddByte(part.Material);
6571 zc.AddByte(part.ClickAction); // clickaction
6572 zc.AddVector3(part.Shape.Scale);
6573
6574 // objectdata block
6575 zc.AddByte(60); // fixed object block size
6576 zc.AddVector3(part.RelativePosition);
6577 zc.AddVector3(part.Velocity);
6578 zc.AddVector3(part.Acceleration);
6579 Quaternion rotation = part.RotationOffset;
6580 rotation.Normalize();
6581 zc.AddNormQuat(rotation);
6582 zc.AddVector3(part.AngularVelocity);
6583
6584 zc.AddUInt(part.ParentID);
6585 zc.AddUInt((uint)primflags); //update flags
6586
6587 //pbs
6588 zc.AddByte(part.Shape.PathCurve);
6589 zc.AddByte(profileCurve);
6590 zc.AddUInt16(part.Shape.PathBegin);
6591 zc.AddUInt16(part.Shape.PathEnd);
6592 zc.AddByte(part.Shape.PathScaleX);
6593 zc.AddByte(pathScaleY);
6594 zc.AddByte(part.Shape.PathShearX);
6595 zc.AddByte(part.Shape.PathShearY);
6596 zc.AddByte((byte)part.Shape.PathTwist);
6597 zc.AddByte((byte)part.Shape.PathTwistBegin);
6598 zc.AddByte((byte)part.Shape.PathRadiusOffset);
6599 zc.AddByte((byte)part.Shape.PathTaperX);
6600 zc.AddByte((byte)part.Shape.PathTaperY);
6601 zc.AddByte(part.Shape.PathRevolutions);
6602 zc.AddByte((byte)part.Shape.PathSkew);
6603 zc.AddUInt16(profileBegin);
6604 zc.AddUInt16(part.Shape.ProfileEnd);
6605 zc.AddUInt16(profileHollow);
6606
6607 // texture
6608 byte[] tentry = part.Shape.TextureEntry;
6609 if (tentry == null)
6610 zc.AddZeros(2);
6611 else
6612 {
6613 int len = tentry.Length;
6614 zc.AddByte((byte)len);
6615 zc.AddByte((byte)(len >> 8));
6616 zc.AddBytes(tentry, len);
6617 }
6618
6619 // texture animation
6620 byte[] tanim = part.TextureAnimation;
6621 if (tanim == null)
6622 zc.AddZeros(1);
6623 else
6624 {
6625 int len = tanim.Length;
6626 zc.AddByte((byte)len);
6627 zc.AddBytes(tanim, len);
6628 }
6629
6630 //NameValue
6631 if(nv == null)
6632 zc.AddZeros(2);
6633 else
6634 {
6635 int len = nv.Length;
6636 zc.AddByte((byte)len);
6637 zc.AddByte((byte)(len >> 8));
6638 zc.AddBytes(nv, len);
6639 }
6640
6641 // data
6642 if (data == null)
6643 zc.AddZeros(2);
6644 else
6645 {
6646 int len = data.Length;
6647 zc.AddByte((byte)len);
6648 zc.AddByte((byte)(len >> 8));
6649 zc.AddBytes(data, len);
6650 }
6651
6652 //text
6653 if (part.Text == null || part.Text.Length == 0)
6654 zc.AddZeros(5);
6655 else
6656 {
6657 byte[] tbuf = Util.StringToBytes(part.Text, 254);
6658 int len = tbuf.Length;
6659 zc.AddByte((byte)len);
6660 zc.AddBytes(tbuf, len);
6661
6662 //textcolor
6663 byte[] tc = part.GetTextColor().GetBytes(false);
6664 zc.AddBytes(tc, 4);
6665 }
6666
6667 //media url
6668 if (part.MediaUrl == null || part.MediaUrl.Length == 0)
6669 zc.AddZeros(1);
6670 else
6671 {
6672 byte[] tbuf = Util.StringToBytes(part.MediaUrl, 255);
6673 int len = tbuf.Length;
6674 zc.AddByte((byte)len);
6675 zc.AddBytes(tbuf, len);
6676 }
6677
6678 bool hasps = false;
6679 //particle system
6680 byte[] ps = part.ParticleSystem;
6681 if (ps == null || ps.Length < 1)
6682 zc.AddZeros(1);
6683 else
6684 {
6685 int len = ps.Length;
6686 zc.AddByte((byte)len);
6687 zc.AddBytes(ps, len);
6688 hasps = true;
6689 }
6690
6691 //Extraparams
6692 byte[] ep = part.Shape.ExtraParams;
6693 if (ep == null || ep.Length < 2)
6694 zc.AddZeros(1);
6695 else
6696 {
6697 int len = ep.Length;
6698 zc.AddByte((byte)len);
6699 zc.AddBytes(ep, len);
6700 }
6701
6702 bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0;
6703 if (hassound)
6704 zc.AddUUID(part.Sound);
6705 else
6706 zc.AddZeros(16);
6707
6708 if (hassound || hasps)
6709 zc.AddUUID(part.OwnerID);
6710 else
6711 zc.AddZeros(16);
6712
6713 if (hassound)
6714 {
6715 zc.AddFloat((float)part.SoundGain);
6716 zc.AddByte(part.SoundFlags);
6717 zc.AddFloat((float)part.SoundRadius);
6718 }
6719 else
6720 zc.AddZeros(9);
6721
6722 // jointtype(1) joint pivot(12) joint offset(12)
6723 const int lastzeros = 1 + 12 + 12;
6724 zc.AddZeros(lastzeros);
6725 }
6726
5885 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) 6727 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
5886 { 6728 {
5887 // TODO: Implement this 6729 // TODO: Implement this
@@ -10047,7 +10889,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10047 10889
10048 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey); 10890 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[1].Parameter), out Prey);
10049 10891
10050 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); 10892 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, false);
10051 } 10893 }
10052 return true; 10894 return true;
10053 case "teleporthomeallusers": 10895 case "teleporthomeallusers":
@@ -10195,7 +11037,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10195 11037
10196 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey); 11038 UUID.TryParse(Utils.BytesToString(messagePacket.ParamList[0].Parameter), out Prey);
10197 11039
10198 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey); 11040 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey, true);
10199 } 11041 }
10200 return true; 11042 return true;
10201 11043
@@ -12560,14 +13402,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12560 /// provide your own method.</param> 13402 /// provide your own method.</param>
12561 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) 13403 protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
12562 { 13404 {
12563
12564/* this is causing packet loss for some reason
12565 if(!m_udpClient.IsConnected)
12566 {
12567 PacketPool.Instance.ReturnPacket(packet);
12568 return;
12569 }
12570*/
12571 if (m_outPacketsToDrop != null) 13405 if (m_outPacketsToDrop != null)
12572 { 13406 {
12573 if (m_outPacketsToDrop.Contains(packet.Type.ToString())) 13407 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 439621a..2981337 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
120 /// <summary>Circuit code that this client is connected on</summary> 120 /// <summary>Circuit code that this client is connected on</summary>
121 public readonly uint CircuitCode; 121 public readonly uint CircuitCode;
122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> 122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
123 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); 123 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256);
124 124
125 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 125 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
126 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 126 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
@@ -210,12 +210,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
210 } 210 }
211 } 211 }
212 212
213 /// <summary>
214 /// This is the percentage of the udp texture queue to add to the task queue since
215 /// textures are now generally handled through http.
216 /// </summary>
217 private double m_cannibalrate = 0.0;
218
219 private ClientInfo m_info = new ClientInfo(); 213 private ClientInfo m_info = new ClientInfo();
220 214
221 /// <summary> 215 /// <summary>
@@ -257,8 +251,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 // Create an array of token buckets for this clients different throttle categories 251 // Create an array of token buckets for this clients different throttle categories
258 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 252 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
259 253
260 m_cannibalrate = rates.CannibalizeTextureRate;
261
262 m_burst = rates.Total * rates.BrustTime; 254 m_burst = rates.Total * rates.BrustTime;
263 255
264 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 256 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
@@ -449,12 +441,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
449 asset = Math.Max(asset, LLUDPServer.MTU); 441 asset = Math.Max(asset, LLUDPServer.MTU);
450*/ 442*/
451 443
452 // Since most textures are now delivered through http, make it possible
453 // to cannibalize some of the bw from the texture throttle to use for
454 // the task queue (e.g. object updates)
455 task = task + (int)(m_cannibalrate * texture);
456 texture = (int)((1 - m_cannibalrate) * texture);
457
458 int total = resend + land + wind + cloud + task + texture + asset; 444 int total = resend + land + wind + cloud + task + texture + asset;
459 445
460 float m_burst = total * m_burstTime; 446 float m_burst = total * m_burstTime;
@@ -575,22 +561,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
575 { 561 {
576 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 562 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
577 563
578 if (m_deliverPackets == false) 564 if (forceQueue || m_deliverPackets == false)
579 { 565 {
580 queue.Enqueue(packet, highPriority); 566 queue.Enqueue(packet, highPriority);
581 return true; 567 return true;
582 } 568 }
583 569
584 TokenBucket bucket = m_throttleCategories[category]; 570 // need to enqueue if queue is not empty
585
586 // Don't send this packet if queue is not empty
587 if (queue.Count > 0 || m_nextPackets[category] != null) 571 if (queue.Count > 0 || m_nextPackets[category] != null)
588 { 572 {
589 queue.Enqueue(packet, highPriority); 573 queue.Enqueue(packet, highPriority);
590 return true; 574 return true;
591 } 575 }
592 576
593 if (!forceQueue && bucket.CheckTokens(packet.Buffer.DataLength)) 577 // check bandwidth
578 TokenBucket bucket = m_throttleCategories[category];
579 if (bucket.CheckTokens(packet.Buffer.DataLength))
594 { 580 {
595 // enough tokens so it can be sent imediatly by caller 581 // enough tokens so it can be sent imediatly by caller
596 bucket.RemoveTokens(packet.Buffer.DataLength); 582 bucket.RemoveTokens(packet.Buffer.DataLength);
@@ -608,7 +594,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
608 // We don't have a token bucket for this category, so it will not be queued 594 // We don't have a token bucket for this category, so it will not be queued
609 return false; 595 return false;
610 } 596 }
611
612 } 597 }
613 598
614 /// <summary> 599 /// <summary>
@@ -650,6 +635,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
650 // leaving a dequeued packet still waiting to be sent out. Try to 635 // leaving a dequeued packet still waiting to be sent out. Try to
651 // send it again 636 // send it again
652 OutgoingPacket nextPacket = m_nextPackets[i]; 637 OutgoingPacket nextPacket = m_nextPackets[i];
638 if(nextPacket.Buffer == null)
639 {
640 if (m_packetOutboxes[i].Count < 5)
641 emptyCategories |= CategoryToFlag(i);
642 continue;
643 }
653 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) 644 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
654 { 645 {
655 // Send the packet 646 // Send the packet
@@ -681,21 +672,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
681 { 672 {
682 // A packet was pulled off the queue. See if we have 673 // A packet was pulled off the queue. See if we have
683 // enough tokens in the bucket to send it out 674 // enough tokens in the bucket to send it out
684 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 675 if(packet.Buffer == null)
685 { 676 {
686 // Send the packet 677 // packet canceled elsewhere (by a ack for example)
687 m_udpServer.SendPacketFinal(packet);
688 packetSent = true;
689
690 if (queue.Count < 5) 678 if (queue.Count < 5)
691 emptyCategories |= CategoryToFlag(i); 679 emptyCategories |= CategoryToFlag(i);
692 } 680 }
693 else 681 else
694 { 682 {
695 // Save the dequeued packet for the next iteration 683 if (bucket.RemoveTokens(packet.Buffer.DataLength))
696 m_nextPackets[i] = packet; 684 {
685 // Send the packet
686 m_udpServer.SendPacketFinal(packet);
687 packetSent = true;
688
689 if (queue.Count < 5)
690 emptyCategories |= CategoryToFlag(i);
691 }
692 else
693 {
694 // Save the dequeued packet for the next iteration
695 m_nextPackets[i] = packet;
696 }
697 } 697 }
698
699 } 698 }
700 else 699 else
701 { 700 {
@@ -803,8 +802,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
803 } 802 }
804 } 803 }
805 804
806
807
808 /// <summary> 805 /// <summary>
809 /// Fires the OnQueueEmpty callback and sets the minimum time that it 806 /// Fires the OnQueueEmpty callback and sets the minimum time that it
810 /// can be called again 807 /// can be called again
@@ -843,6 +840,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 return 0; 840 return 0;
844 } 841 }
845 842
843 public void FreeUDPBuffer(UDPPacketBuffer buf)
844 {
845 m_udpServer.FreeUDPBuffer(buf);
846 }
847
846 /// <summary> 848 /// <summary>
847 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a 849 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
848 /// flag value 850 /// flag value
@@ -853,34 +855,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
853 { 855 {
854 ThrottleOutPacketType category = (ThrottleOutPacketType)i; 856 ThrottleOutPacketType category = (ThrottleOutPacketType)i;
855 857
856 /*
857 * Land = 1,
858 /// <summary>Wind data</summary>
859 Wind = 2,
860 /// <summary>Cloud data</summary>
861 Cloud = 3,
862 /// <summary>Any packets that do not fit into the other throttles</summary>
863 Task = 4,
864 /// <summary>Texture assets</summary>
865 Texture = 5,
866 /// <summary>Non-texture assets</summary>
867 Asset = 6,
868 */
869
870 switch (category) 858 switch (category)
871 { 859 {
872 case ThrottleOutPacketType.Land: 860 case ThrottleOutPacketType.Land:
873 return ThrottleOutPacketTypeFlags.Land; 861 return ThrottleOutPacketTypeFlags.Land; // Terrain data
874 case ThrottleOutPacketType.Wind: 862 case ThrottleOutPacketType.Wind:
875 return ThrottleOutPacketTypeFlags.Wind; 863 return ThrottleOutPacketTypeFlags.Wind; // Wind data
876 case ThrottleOutPacketType.Cloud: 864 case ThrottleOutPacketType.Cloud:
877 return ThrottleOutPacketTypeFlags.Cloud; 865 return ThrottleOutPacketTypeFlags.Cloud; // Cloud data
878 case ThrottleOutPacketType.Task: 866 case ThrottleOutPacketType.Task:
879 return ThrottleOutPacketTypeFlags.Task; 867 return ThrottleOutPacketTypeFlags.Task; // Object updates and everything not on the other categories
880 case ThrottleOutPacketType.Texture: 868 case ThrottleOutPacketType.Texture:
881 return ThrottleOutPacketTypeFlags.Texture; 869 return ThrottleOutPacketTypeFlags.Texture; // Textures data (also impacts http texture and mesh by default)
882 case ThrottleOutPacketType.Asset: 870 case ThrottleOutPacketType.Asset:
883 return ThrottleOutPacketTypeFlags.Asset; 871 return ThrottleOutPacketTypeFlags.Asset; // Non-texture Assets data
884 default: 872 default:
885 return 0; 873 return 0;
886 } 874 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 35d29a5..2300800 100644..100755
--- 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
256 256
257 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> 257 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
258 public const int MTU = 1400; 258 public const int MTU = 1400;
259 public const int MAXPAYLOAD = 1250;
259 260
260 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> 261 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
261 public int ClientLogoutsDueToNoReceives { get; protected set; } 262 public int ClientLogoutsDueToNoReceives { get; protected set; }
@@ -274,10 +275,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
274 /// <summary>The measured resolution of Environment.TickCount</summary> 275 /// <summary>The measured resolution of Environment.TickCount</summary>
275 public readonly float TickCountResolution; 276 public readonly float TickCountResolution;
276 277
277 /// <summary>Number of prim updates to put on the queue each time the
278 /// OnQueueEmpty event is triggered for updates</summary>
279 public readonly int PrimUpdatesPerCallback;
280
281 /// <summary>Number of texture packets to put on the queue each time the 278 /// <summary>Number of texture packets to put on the queue each time the
282 /// OnQueueEmpty event is triggered for textures</summary> 279 /// OnQueueEmpty event is triggered for textures</summary>
283 public readonly int TextureSendLimit; 280 public readonly int TextureSendLimit;
@@ -344,18 +341,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
344 341
345 protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 342 protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
346 343
347 protected Pool<IncomingPacket> m_incomingPacketPool;
348
349 /// <summary>
350 /// Stat for number of packets in the main pool awaiting use.
351 /// </summary>
352 protected Stat m_poolCountStat;
353
354 /// <summary>
355 /// Stat for number of packets in the inbound packet pool awaiting use.
356 /// </summary>
357 protected Stat m_incomingPacketPoolStat;
358
359 protected int m_defaultRTO = 0; 344 protected int m_defaultRTO = 0;
360 protected int m_maxRTO = 0; 345 protected int m_maxRTO = 0;
361 protected int m_ackTimeout = 0; 346 protected int m_ackTimeout = 0;
@@ -452,7 +437,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
452 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); 437 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
453 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 438 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
454 439
455 PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
456 TextureSendLimit = config.GetInt("TextureSendLimit", 20); 440 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
457 441
458 m_defaultRTO = config.GetInt("DefaultRTO", 0); 442 m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -463,7 +447,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
463 } 447 }
464 else 448 else
465 { 449 {
466 PrimUpdatesPerCallback = 100;
467 TextureSendLimit = 20; 450 TextureSendLimit = 20;
468 m_ackTimeout = 1000 * 60; // 1 minute 451 m_ackTimeout = 1000 * 60; // 1 minute
469 m_pausedAckTimeout = 1000 * 300; // 5 minutes 452 m_pausedAckTimeout = 1000 * 300; // 5 minutes
@@ -498,7 +481,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
498 481
499// if (usePools) 482// if (usePools)
500// EnablePools(); 483// EnablePools();
501 base.DisablePools();
502 } 484 }
503 485
504 public void Start() 486 public void Start()
@@ -554,83 +536,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
554 OqrEngine.Stop(); 536 OqrEngine.Stop();
555 } 537 }
556 538
557 public override bool EnablePools()
558 {
559 if (!UsePools)
560 {
561 base.EnablePools();
562
563 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
564
565 return true;
566 }
567
568 return false;
569 }
570
571 public override bool DisablePools()
572 {
573 if (UsePools)
574 {
575 base.DisablePools();
576
577 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
578
579 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
580
581 return true;
582 }
583
584 return false;
585 }
586
587 /// <summary>
588 /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
589 /// stats.
590 /// </summary>
591 protected internal void EnablePoolStats()
592 {
593 m_poolCountStat
594 = new Stat(
595 "UDPPacketBufferPoolCount",
596 "Objects within the UDPPacketBuffer pool",
597 "The number of objects currently stored within the UDPPacketBuffer pool",
598 "",
599 "clientstack",
600 Scene.Name,
601 StatType.Pull,
602 stat => stat.Value = Pool.Count,
603 StatVerbosity.Debug);
604
605 StatsManager.RegisterStat(m_poolCountStat);
606
607 m_incomingPacketPoolStat
608 = new Stat(
609 "IncomingPacketPoolCount",
610 "Objects within incoming packet pool",
611 "The number of objects currently stored within the incoming packet pool",
612 "",
613 "clientstack",
614 Scene.Name,
615 StatType.Pull,
616 stat => stat.Value = m_incomingPacketPool.Count,
617 StatVerbosity.Debug);
618
619 StatsManager.RegisterStat(m_incomingPacketPoolStat);
620 }
621
622 /// <summary>
623 /// Disables pool stats.
624 /// </summary>
625 protected internal void DisablePoolStats()
626 {
627 StatsManager.DeregisterStat(m_poolCountStat);
628 m_poolCountStat = null;
629
630 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
631 m_incomingPacketPoolStat = null;
632 }
633
634 /// <summary> 539 /// <summary>
635 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. 540 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
636 /// </summary> 541 /// </summary>
@@ -658,8 +563,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
658 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), 563 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name),
659 "INCOMING PACKET ASYNC HANDLING ENGINE"); 564 "INCOMING PACKET ASYNC HANDLING ENGINE");
660*/ 565*/
661 OqrEngine 566 OqrEngine = new JobEngine(
662 = new JobEngine(
663 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), 567 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
664 "OUTGOING QUEUE REFILL ENGINE"); 568 "OUTGOING QUEUE REFILL ENGINE");
665 569
@@ -769,15 +673,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
769 stat => stat.Value = OqrEngine.JobsWaiting, 673 stat => stat.Value = OqrEngine.JobsWaiting,
770 StatVerbosity.Debug)); 674 StatVerbosity.Debug));
771 675
772 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by 676 StatsManager.RegisterStat(
773 // scene name 677 new Stat(
774 if (UsePools) 678 "UDPBuffersPoolCount",
775 EnablePoolStats(); 679 "Buffers in the UDP buffers pool",
776 680 "The number of buffers currently stored within the UDP buffers pool",
681 "",
682 "clientstack",
683 Scene.Name,
684 StatType.Pull,
685 stat => stat.Value = m_udpBuffersPoolPtr + 1,
686 StatVerbosity.Debug));
777 687
778 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 688 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
779 commands.Register(); 689 commands.Register();
780
781 } 690 }
782 691
783 public bool HandlesRegion(Location x) 692 public bool HandlesRegion(Location x)
@@ -939,9 +848,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
939 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting 848 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
940 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here 849 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
941 // to accomodate for both common scenarios and provide ample room for ACK appending in both 850 // to accomodate for both common scenarios and provide ample room for ACK appending in both
942 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; 851 //int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
943 852
944 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 853 //UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
854 UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
945 855
946 // Zerocode if needed 856 // Zerocode if needed
947 if (doZerocode) 857 if (doZerocode)
@@ -971,7 +881,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
971 // If the packet data wasn't already copied during zerocoding, copy it now 881 // If the packet data wasn't already copied during zerocoding, copy it now
972 if (doCopy) 882 if (doCopy)
973 { 883 {
974 if (dataLength <= buffer.Data.Length) 884 //if (dataLength <= buffer.Data.Length)
885 if (dataLength <= LLUDPServer.MTU)
975 { 886 {
976 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 887 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
977 } 888 }
@@ -979,7 +890,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 { 890 {
980 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + 891 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
981 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length); 892 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
982 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength); 893 // buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, dataLength);
894 buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint);
983 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 895 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
984 } 896 }
985 } 897 }
@@ -1017,6 +929,89 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1017 #endregion Queue or Send 929 #endregion Queue or Send
1018 } 930 }
1019 931
932 public unsafe UDPPacketBuffer ZeroEncode(UDPPacketBuffer input)
933 {
934 UDPPacketBuffer zb = GetNewUDPBuffer(null);
935 int srclen = input.DataLength;
936 byte[] src = input.Data;
937 byte[] dest = zb.Data;
938
939 int zerolen = 6;
940 byte zerocount = 0;
941
942 for (int i = zerolen; i < srclen; i++)
943 {
944 if (src[i] == 0x00)
945 {
946 zerocount++;
947 if (zerocount == 0)
948 {
949 dest[zerolen++] = 0x00;
950 dest[zerolen++] = 0xff;
951 zerocount++;
952 }
953 }
954 else
955 {
956 if (zerocount != 0)
957 {
958 dest[zerolen++] = 0x00;
959 dest[zerolen++] = zerocount;
960 zerocount = 0;
961 }
962
963 dest[zerolen++] = src[i];
964 }
965 }
966
967 if (zerocount != 0)
968 {
969 dest[zerolen++] = 0x00;
970 dest[zerolen++] = zerocount;
971 }
972
973 if(zerolen >= srclen)
974 {
975 FreeUDPBuffer(zb);
976
977 src[0] &= unchecked((byte)~Helpers.MSG_ZEROCODED);
978 return input;
979 }
980
981 Buffer.BlockCopy(src, 0, dest, 0, 6);
982
983 zb.RemoteEndPoint = input.RemoteEndPoint;
984 zb.DataLength = zerolen;
985
986 FreeUDPBuffer(input);
987
988 return zb;
989 }
990
991 public void SendUDPPacket(
992 LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode)
993 {
994 bool highPriority = false;
995
996 if(zerocode)
997 buffer = ZeroEncode(buffer);
998
999 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
1000 {
1001 category = (ThrottleOutPacketType)((int)category & 127);
1002 highPriority = true;
1003 }
1004
1005 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
1006
1007 // If we were not provided a method for handling unacked, use the UDPServer default method
1008 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
1009 outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
1010
1011 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forcequeue, highPriority))
1012 SendPacketFinal(outgoingPacket);
1013 }
1014
1020 public void SendAcks(LLUDPClient udpClient) 1015 public void SendAcks(LLUDPClient udpClient)
1021 { 1016 {
1022 uint ack; 1017 uint ack;
@@ -1066,7 +1061,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1066 { 1061 {
1067 LLUDPClient udpClient = client.UDPClient; 1062 LLUDPClient udpClient = client.UDPClient;
1068 1063
1069 if (!udpClient.IsConnected) 1064 if (!client.IsActive || !udpClient.IsConnected)
1070 return; 1065 return;
1071 1066
1072 // Disconnect an agent if no packets are received for some time 1067 // Disconnect an agent if no packets are received for some time
@@ -1136,14 +1131,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1136 internal void SendPacketFinal(OutgoingPacket outgoingPacket) 1131 internal void SendPacketFinal(OutgoingPacket outgoingPacket)
1137 { 1132 {
1138 UDPPacketBuffer buffer = outgoingPacket.Buffer; 1133 UDPPacketBuffer buffer = outgoingPacket.Buffer;
1134 if(buffer == null) // canceled packet
1135 return;
1136 LLUDPClient udpClient = outgoingPacket.Client;
1137 if (!udpClient.IsConnected)
1138 return;
1139
1139 byte flags = buffer.Data[0]; 1140 byte flags = buffer.Data[0];
1140 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 1141 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
1141 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; 1142 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
1142 bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0; 1143 bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
1143 LLUDPClient udpClient = outgoingPacket.Client;
1144
1145 if (!udpClient.IsConnected)
1146 return;
1147 1144
1148 int dataLength = buffer.DataLength; 1145 int dataLength = buffer.DataLength;
1149 1146
@@ -1154,7 +1151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1154 // no more ACKs to append 1151 // no more ACKs to append
1155 int ackCount = 0; 1152 int ackCount = 0;
1156 uint ack; 1153 uint ack;
1157 while (dataLength + 5 < buffer.Data.Length && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack)) 1154 while (dataLength + 5 < MTU && ackCount < 256 && udpClient.PendingAcks.Dequeue(out ack))
1158 { 1155 {
1159 Utils.UIntToBytesBig(ack, buffer.Data, dataLength); 1156 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
1160 dataLength += 4; 1157 dataLength += 4;
@@ -1168,22 +1165,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1168 // Set the appended ACKs flag on this packet 1165 // Set the appended ACKs flag on this packet
1169 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); 1166 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
1170 } 1167 }
1168 buffer.DataLength = dataLength;
1171 } 1169 }
1172 1170
1173 buffer.DataLength = dataLength;
1174
1175 if (!isResend) 1171 if (!isResend)
1176 { 1172 {
1177 // Not a resend, assign a new sequence number 1173 // Not a resend, assign a new sequence number
1178 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence); 1174 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
1179 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 1175 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
1180 outgoingPacket.SequenceNumber = sequenceNumber; 1176 outgoingPacket.SequenceNumber = sequenceNumber;
1181
1182 if (isReliable)
1183 {
1184 // Add this packet to the list of ACK responses we are waiting on from the server
1185 udpClient.NeedAcks.Add(outgoingPacket);
1186 }
1187 } 1177 }
1188 else 1178 else
1189 { 1179 {
@@ -1196,9 +1186,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1196 PacketsSentCount++; 1186 PacketsSentCount++;
1197 1187
1198 SyncSend(buffer); 1188 SyncSend(buffer);
1189
1199 // Keep track of when this packet was sent out (right now) 1190 // Keep track of when this packet was sent out (right now)
1200 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1191 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1201 1192
1193 if (outgoingPacket.UnackedMethod == null)
1194 FreeUDPBuffer(buffer);
1195 else if(!isResend)
1196 {
1197 // Add this packet to the list of ACK responses we are waiting on from the server
1198 udpClient.NeedAcks.Add(outgoingPacket);
1199 }
1200
1202 if (udpClient.DebugDataOutLevel > 0) 1201 if (udpClient.DebugDataOutLevel > 0)
1203 m_log.DebugFormat( 1202 m_log.DebugFormat(
1204 "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}", 1203 "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}",
@@ -1240,7 +1239,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1240// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1239// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1241 1240
1242 RecordMalformedInboundPacket(endPoint); 1241 RecordMalformedInboundPacket(endPoint);
1243 1242 FreeUDPBuffer(buffer);
1244 return; // Drop undersized packet 1243 return; // Drop undersized packet
1245 } 1244 }
1246 1245
@@ -1260,21 +1259,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1260// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1259// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1261 1260
1262 RecordMalformedInboundPacket(endPoint); 1261 RecordMalformedInboundPacket(endPoint);
1263 1262 FreeUDPBuffer(buffer);
1264 return; // Malformed header 1263 return; // Malformed header
1265 } 1264 }
1266 1265
1267 try 1266 try
1268 { 1267 {
1269// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 1268 // get a buffer for zero decode using the udp buffers pool
1270// // Only allocate a buffer for zerodecoding if the packet is zerocoded 1269 UDPPacketBuffer zerodecodebufferholder = null;
1271// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1270 byte[] zerodecodebuffer = null;
1271 // only if needed
1272 if (((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0))
1273 {
1274 zerodecodebufferholder = GetNewUDPBuffer(null);
1275 zerodecodebuffer = zerodecodebufferholder.Data;
1276 }
1277
1278 packet = Packet.BuildPacket(buffer.Data, ref packetEnd, zerodecodebuffer);
1272 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we 1279 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
1273 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all 1280 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
1274 // bytes are copied out). 1281 // bytes are copied out).
1275 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, 1282 // packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, zerodecodebuffer);
1276 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1283 if(zerodecodebufferholder != null)
1277 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1284 FreeUDPBuffer(zerodecodebufferholder);
1278 } 1285 }
1279 catch (Exception e) 1286 catch (Exception e)
1280 { 1287 {
@@ -1292,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1292 } 1299 }
1293 1300
1294 RecordMalformedInboundPacket(endPoint); 1301 RecordMalformedInboundPacket(endPoint);
1295 1302 FreeUDPBuffer(buffer);
1296 return; 1303 return;
1297 } 1304 }
1298 1305
@@ -1311,17 +1318,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1311 lock (m_pendingCache) 1318 lock (m_pendingCache)
1312 { 1319 {
1313 if (m_pendingCache.Contains(endPoint)) 1320 if (m_pendingCache.Contains(endPoint))
1321 {
1322 FreeUDPBuffer(buffer);
1314 return; 1323 return;
1324 }
1315 1325
1316 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); 1326 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1317 } 1327 }
1318 1328
1319 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1329 Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet });
1320 // buffer. 1330 FreeUDPBuffer(buffer);
1321 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1322
1323 Util.FireAndForget(HandleUseCircuitCode, array);
1324
1325 return; 1331 return;
1326 } 1332 }
1327 } 1333 }
@@ -1336,24 +1342,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1336 queue.Enqueue(buffer); 1342 queue.Enqueue(buffer);
1337 return; 1343 return;
1338 } 1344 }
1339
1340/*
1341 else if (packet.Type == PacketType.CompleteAgentMovement)
1342 {
1343 // Send ack straight away to let the viewer know that we got it.
1344 SendAckImmediate(endPoint, packet.Header.Sequence);
1345
1346 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1347 // buffer.
1348 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1349
1350 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1351
1352 return;
1353 }
1354 */
1355 } 1345 }
1356 1346
1347 FreeUDPBuffer(buffer);
1348
1357 // Determine which agent this packet came from 1349 // Determine which agent this packet came from
1358 if (client == null || !(client is LLClientView)) 1350 if (client == null || !(client is LLClientView))
1359 { 1351 {
@@ -1471,10 +1463,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1471 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1463 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1472 #endregion BinaryStats 1464 #endregion BinaryStats
1473 1465
1474
1475//AgentUpdate removed from here
1476
1477
1478 #region Ping Check Handling 1466 #region Ping Check Handling
1479 1467
1480 if (packet.Type == PacketType.StartPingCheck) 1468 if (packet.Type == PacketType.StartPingCheck)
@@ -1506,17 +1494,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1506 1494
1507 IncomingPacket incomingPacket; 1495 IncomingPacket incomingPacket;
1508 1496
1509 // Inbox insertion 1497 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1510 if (UsePools)
1511 {
1512 incomingPacket = m_incomingPacketPool.GetObject();
1513 incomingPacket.Client = (LLClientView)client;
1514 incomingPacket.Packet = packet;
1515 }
1516 else
1517 {
1518 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1519 }
1520 1498
1521// if (incomingPacket.Packet.Type == PacketType.AgentUpdate || 1499// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1522// incomingPacket.Packet.Type == PacketType.ChatFromViewer) 1500// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
@@ -1525,7 +1503,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1525// else 1503// else
1526// packetInbox.Enqueue(incomingPacket); 1504// packetInbox.Enqueue(incomingPacket);
1527 packetInbox.Add(incomingPacket); 1505 packetInbox.Add(incomingPacket);
1528
1529 } 1506 }
1530 1507
1531 #region BinaryStats 1508 #region BinaryStats
@@ -1685,7 +1662,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1685 { 1662 {
1686 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1663 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1687 return; 1664 return;
1688
1689 } 1665 }
1690 m_pendingCache.Remove(endPoint); 1666 m_pendingCache.Remove(endPoint);
1691 } 1667 }
@@ -1881,13 +1857,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1881 byte[] packetData = ack.ToBytes(); 1857 byte[] packetData = ack.ToBytes();
1882 int length = packetData.Length; 1858 int length = packetData.Length;
1883 1859
1884 UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); 1860 UDPPacketBuffer buffer = GetNewUDPBuffer(remoteEndpoint);
1885 buffer.DataLength = length; 1861 buffer.DataLength = length;
1886 1862
1887 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); 1863 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
1888 1864
1889// AsyncBeginSend(buffer); 1865// AsyncBeginSend(buffer);
1890 SyncSend(buffer); 1866 SyncSend(buffer);
1867 FreeUDPBuffer(buffer);
1891 } 1868 }
1892 1869
1893 protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) 1870 protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
@@ -1982,21 +1959,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1982 Scene.ThreadAlive(1); 1959 Scene.ThreadAlive(1);
1983 try 1960 try
1984 { 1961 {
1985 packetInbox.TryTake(out incomingPacket, 250); 1962 packetInbox.TryTake(out incomingPacket, 4500);
1986 1963
1987 if (incomingPacket != null && IsRunningInbound) 1964 if (incomingPacket != null && IsRunningInbound)
1988 { 1965 {
1989 ProcessInPacket(incomingPacket); 1966 ProcessInPacket(incomingPacket);
1990
1991 if (UsePools)
1992 {
1993 incomingPacket.Client = null;
1994 m_incomingPacketPool.ReturnObject(incomingPacket);
1995 }
1996 incomingPacket = null; 1967 incomingPacket = null;
1997 } 1968 }
1998 } 1969 }
1999 catch(Exception ex) 1970 catch (ThreadAbortException)
1971 {
1972 Thread.ResetAbort();
1973 }
1974 catch (Exception ex)
2000 { 1975 {
2001 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 1976 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
2002 } 1977 }
@@ -2025,7 +2000,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2025 { 2000 {
2026 Scene.ThreadAlive(2); 2001 Scene.ThreadAlive(2);
2027 2002
2028
2029 try 2003 try
2030 { 2004 {
2031 m_packetSent = false; 2005 m_packetSent = false;
@@ -2080,7 +2054,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2080 } 2054 }
2081 else if (!m_packetSent) 2055 else if (!m_packetSent)
2082// Thread.Sleep((int)TickCountResolution); outch this is bad on linux 2056// Thread.Sleep((int)TickCountResolution); outch this is bad on linux
2083 Thread.Sleep(15); // match the 16ms of windows7, dont ask 16 or win may decide to do 32ms. 2057 Thread.Sleep(15); // match the 16ms of windows, dont ask 16 or win may decide to do 32ms.
2084 2058
2085 Watchdog.UpdateThread(); 2059 Watchdog.UpdateThread();
2086 } 2060 }
@@ -2104,14 +2078,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2104 2078
2105 if (udpClient.IsConnected) 2079 if (udpClient.IsConnected)
2106 { 2080 {
2107 if (m_resendUnacked) 2081 if (client.IsActive && m_resendUnacked)
2108 HandleUnacked(llClient); 2082 HandleUnacked(llClient);
2109 2083
2110 if (m_sendAcks) 2084 if (client.IsActive)
2111 SendAcks(udpClient); 2085 {
2086 if (m_sendAcks)
2087 SendAcks(udpClient);
2112 2088
2113 if (m_sendPing) 2089 if (m_sendPing)
2114 SendPing(udpClient); 2090 SendPing(udpClient);
2091 }
2115 2092
2116 // Dequeue any outgoing packets that are within the throttle limits 2093 // Dequeue any outgoing packets that are within the throttle limits
2117 if (udpClient.DequeueOutgoing()) 2094 if (udpClient.DequeueOutgoing())
@@ -2124,7 +2101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2124 m_log.Error( 2101 m_log.Error(
2125 string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex); 2102 string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex);
2126 } 2103 }
2127 client = null;
2128 } 2104 }
2129 2105
2130 #region Emergency Monitoring 2106 #region Emergency Monitoring
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
index 012a57d..a4d7eb9 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
777 m_udpServer.StopOutbound(); 777 m_udpServer.StopOutbound();
778 } 778 }
779 779
780 private void HandlePoolCommand(string module, string[] args)
781 {
782 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
783 return;
784
785 if (args.Length != 4)
786 {
787 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
788 return;
789 }
790
791 string enabled = args[3];
792
793 if (enabled == "on")
794 {
795 if (m_udpServer.EnablePools())
796 {
797 m_udpServer.EnablePoolStats();
798 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_udpServer.Scene.Name);
799 }
800 }
801 else if (enabled == "off")
802 {
803 if (m_udpServer.DisablePools())
804 {
805 m_udpServer.DisablePoolStats();
806 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_udpServer.Scene.Name);
807 }
808 }
809 else
810 {
811 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
812 }
813 }
814
815 private void HandleAgentUpdateCommand(string module, string[] args) 780 private void HandleAgentUpdateCommand(string module, string[] args)
816 { 781 {
817 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) 782 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
@@ -834,8 +799,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 MainConsole.Instance.OutputFormat( 799 MainConsole.Instance.OutputFormat(
835 "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled"); 800 "OUT LLUDP packet processing for {0} is {1}", m_udpServer.Scene.Name, m_udpServer.IsRunningOutbound ? "enabled" : "disabled");
836 801
837 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_udpServer.Scene.Name, m_udpServer.UsePools ? "on" : "off");
838
839 MainConsole.Instance.OutputFormat( 802 MainConsole.Instance.OutputFormat(
840 "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel); 803 "Packet debug level for new clients is {0}", m_udpServer.DefaultClientPacketDebugLevel);
841 } 804 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs
new file mode 100644
index 0000000..8ed2cf1
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs
@@ -0,0 +1,279 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Framework;
30using Nini.Config;
31using OpenMetaverse;
32
33namespace OpenSim.Region.ClientStack.LindenUDP
34{
35 public sealed class LLUDPZeroEncoder
36 {
37 private byte[] m_tmp = new byte[16];
38 private byte[] m_dest;
39 private int zerocount;
40 private int pos;
41
42 public LLUDPZeroEncoder()
43 {
44 }
45
46 public LLUDPZeroEncoder(byte[] data)
47 {
48 m_dest = data;
49 zerocount = 0;
50 }
51
52 public byte[] Data
53 {
54 get
55 {
56 return m_dest;
57 }
58 set
59 {
60 m_dest = value;
61 }
62 }
63
64 public int ZeroCount
65 {
66 get
67 {
68 return zerocount;
69 }
70 set
71 {
72 zerocount = value;
73 }
74 }
75
76 public int Position
77 {
78 get
79 {
80 return pos;
81 }
82 set
83 {
84 pos = value;
85 }
86 }
87
88 public unsafe void AddZeros(int len)
89 {
90 zerocount += len;
91 while (zerocount > 255)
92 {
93 m_dest[pos++] = 0x00;
94 m_dest[pos++] = 0xff;
95 zerocount -= 256;
96 }
97 }
98
99 public unsafe int Finish()
100 {
101 if(zerocount > 0)
102 {
103 m_dest[pos++] = 0x00;
104 m_dest[pos++] = (byte)zerocount;
105 }
106 return pos;
107 }
108
109 public unsafe void AddBytes(byte[] src, int srclen)
110 {
111 for (int i = 0; i < srclen; ++i)
112 {
113 if (src[i] == 0x00)
114 {
115 zerocount++;
116 if (zerocount == 0)
117 {
118 m_dest[pos++] = 0x00;
119 m_dest[pos++] = 0xff;
120 zerocount++;
121 }
122 }
123 else
124 {
125 if (zerocount != 0)
126 {
127 m_dest[pos++] = 0x00;
128 m_dest[pos++] = (byte)zerocount;
129 zerocount = 0;
130 }
131
132 m_dest[pos++] = src[i];
133 }
134 }
135 }
136
137 public unsafe void AddByte(byte v)
138 {
139 if (v == 0x00)
140 {
141 zerocount++;
142 if (zerocount == 0)
143 {
144 m_dest[pos++] = 0x00;
145 m_dest[pos++] = 0xff;
146 zerocount++;
147 }
148 }
149 else
150 {
151 if (zerocount != 0)
152 {
153 m_dest[pos++] = 0x00;
154 m_dest[pos++] = (byte)zerocount;
155 zerocount = 0;
156 }
157
158 m_dest[pos++] = v;
159 }
160 }
161
162 public void AddInt16(short v)
163 {
164 if (v == 0)
165 AddZeros(2);
166 else
167 {
168 Utils.Int16ToBytes(v, m_tmp, 0);
169 AddBytes(m_tmp, 2);
170 }
171 }
172
173 public void AddUInt16(ushort v)
174 {
175 if (v == 0)
176 AddZeros(2);
177 else
178 {
179 Utils.UInt16ToBytes(v, m_tmp, 0);
180 AddBytes(m_tmp, 2);
181 }
182 }
183
184 public void AddInt(int v)
185 {
186 if (v == 0)
187 AddZeros(4);
188 else
189 {
190 Utils.IntToBytesSafepos(v, m_tmp, 0);
191 AddBytes(m_tmp, 4);
192 }
193 }
194
195 public unsafe void AddUInt(uint v)
196 {
197 if (v == 0)
198 AddZeros(4);
199 else
200 {
201 Utils.UIntToBytesSafepos(v, m_tmp, 0);
202 AddBytes(m_tmp, 4);
203 }
204 }
205
206 public void AddFloatToUInt16(float v, float range)
207 {
208 Utils.FloatToUInt16Bytes(v, range, m_tmp, 0);
209 AddBytes(m_tmp, 2);
210 }
211
212 public void AddFloat(float v)
213 {
214 if (v == 0f)
215 AddZeros(4);
216 else
217 {
218 Utils.FloatToBytesSafepos(v, m_tmp, 0);
219 AddBytes(m_tmp, 4);
220 }
221 }
222
223 public void AddInt64(long v)
224 {
225 if (v == 0)
226 AddZeros(8);
227 else
228 {
229 Utils.Int64ToBytesSafepos(v, m_tmp, 0);
230 AddBytes(m_tmp, 8);
231 }
232 }
233
234 public void AddUInt64(ulong v)
235 {
236 if (v == 0)
237 AddZeros(8);
238 else
239 {
240 Utils.UInt64ToBytesSafepos(v, m_tmp, 0);
241 AddBytes(m_tmp, 8);
242 }
243 }
244
245 public void AddVector3(Vector3 v)
246 {
247 if (v == Vector3.Zero)
248 AddZeros(12);
249 else
250 {
251 v.ToBytes(m_tmp, 0);
252 AddBytes(m_tmp, 12);
253 }
254 }
255
256 public void AddVector4(Vector4 v)
257 {
258 if (v == Vector4.Zero)
259 AddZeros(16);
260 else
261 {
262 v.ToBytes(m_tmp, 0);
263 AddBytes(m_tmp, 16);
264 }
265 }
266
267 public void AddNormQuat(Quaternion v)
268 {
269 v.ToBytes(m_tmp, 0);
270 AddBytes(m_tmp, 12);
271 }
272
273 public void AddUUID(UUID v)
274 {
275 v.ToBytes(m_tmp, 0);
276 AddBytes(m_tmp, 16);
277 }
278 }
279}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f362b06..49aca3c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Concurrent;
29using System.Net; 30using System.Net;
30using System.Net.Sockets; 31using System.Net.Sockets;
31using System.Threading; 32using System.Threading;
@@ -57,15 +58,9 @@ namespace OpenMetaverse
57 /// <summary>UDP socket, used in either client or server mode</summary> 58 /// <summary>UDP socket, used in either client or server mode</summary>
58 private Socket m_udpSocket; 59 private Socket m_udpSocket;
59 60
60 /// <summary> 61 public static Object m_udpBuffersPoolLock = new Object();
61 /// Are we to use object pool(s) to reduce memory churn when receiving data? 62 public static UDPPacketBuffer[] m_udpBuffersPool = new UDPPacketBuffer[1000];
62 /// </summary> 63 public static int m_udpBuffersPoolPtr = -1;
63 public bool UsePools { get; protected set; }
64
65 /// <summary>
66 /// Pool to use for handling data. May be null if UsePools = false;
67 /// </summary>
68 protected OpenSim.Framework.Pool<UDPPacketBuffer> Pool { get; private set; }
69 64
70 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary> 65 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
71 public bool IsRunningInbound { get; private set; } 66 public bool IsRunningInbound { get; private set; }
@@ -186,6 +181,37 @@ namespace OpenMetaverse
186 if(m_udpSocket !=null) 181 if(m_udpSocket !=null)
187 try { m_udpSocket.Close(); } catch { } 182 try { m_udpSocket.Close(); } catch { }
188 } 183 }
184
185 public UDPPacketBuffer GetNewUDPBuffer(IPEndPoint remoteEndpoint)
186 {
187 lock (m_udpBuffersPoolLock)
188 {
189 if (m_udpBuffersPoolPtr >= 0)
190 {
191 UDPPacketBuffer buf = m_udpBuffersPool[m_udpBuffersPoolPtr];
192 m_udpBuffersPool[m_udpBuffersPoolPtr] = null;
193 m_udpBuffersPoolPtr--;
194 buf.RemoteEndPoint = remoteEndpoint;
195 return buf;
196 }
197 }
198 return new UDPPacketBuffer(remoteEndpoint);
199 }
200
201 public void FreeUDPBuffer(UDPPacketBuffer buf)
202 {
203 lock (m_udpBuffersPoolLock)
204 {
205 if (m_udpBuffersPoolPtr < 999)
206 {
207 buf.RemoteEndPoint = null;
208 buf.DataLength = 0;
209 m_udpBuffersPoolPtr++;
210 m_udpBuffersPool[m_udpBuffersPoolPtr] = buf;
211 }
212 }
213 }
214
189 /// <summary> 215 /// <summary>
190 /// Start inbound UDP packet handling. 216 /// Start inbound UDP packet handling.
191 /// </summary> 217 /// </summary>
@@ -202,6 +228,7 @@ namespace OpenMetaverse
202 /// manner (not throwing an exception when the remote side resets the 228 /// manner (not throwing an exception when the remote side resets the
203 /// connection). This call is ignored on Mono where the flag is not 229 /// connection). This call is ignored on Mono where the flag is not
204 /// necessary</remarks> 230 /// necessary</remarks>
231
205 public virtual void StartInbound(int recvBufferSize) 232 public virtual void StartInbound(int recvBufferSize)
206 { 233 {
207 if (!IsRunningInbound) 234 if (!IsRunningInbound)
@@ -306,102 +333,56 @@ namespace OpenMetaverse
306 IsRunningOutbound = false; 333 IsRunningOutbound = false;
307 } 334 }
308 335
309 public virtual bool EnablePools() 336 private void AsyncBeginReceive()
310 { 337 {
311 if (!UsePools) 338 if (!IsRunningInbound)
312 { 339 return;
313 Pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
314
315 UsePools = true;
316
317 return true;
318 }
319
320 return false;
321 }
322 340
323 public virtual bool DisablePools() 341 UDPPacketBuffer buf = GetNewUDPBuffer(new IPEndPoint(IPAddress.Any, 0)); // we need a fresh one here, for now at least
324 { 342 try
325 if (UsePools)
326 { 343 {
327 UsePools = false; 344 // kick off an async read
328 345 m_udpSocket.BeginReceiveFrom(
329 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. 346 buf.Data,
330 347 0,
331 return true; 348 buf.Data.Length,
349 SocketFlags.None,
350 ref buf.RemoteEndPoint,
351 AsyncEndReceive,
352 buf);
332 } 353 }
333 354 catch (SocketException e)
334 return false;
335 }
336
337 private void AsyncBeginReceive()
338 {
339 UDPPacketBuffer buf;
340
341 // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other
342 // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux.
343 // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads. Requires more investigation.
344// if (UsePools)
345// buf = Pool.GetObject();
346// else
347 buf = new UDPPacketBuffer();
348
349 if (IsRunningInbound)
350 { 355 {
351 try 356 if (e.SocketErrorCode == SocketError.ConnectionReset)
352 {
353 // kick off an async read
354 m_udpSocket.BeginReceiveFrom(
355 //wrappedBuffer.Instance.Data,
356 buf.Data,
357 0,
358 UDPPacketBuffer.BUFFER_SIZE,
359 SocketFlags.None,
360 ref buf.RemoteEndPoint,
361 AsyncEndReceive,
362 //wrappedBuffer);
363 buf);
364 }
365 catch (SocketException e)
366 { 357 {
367 if (e.SocketErrorCode == SocketError.ConnectionReset) 358 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
359 bool salvaged = false;
360 while (!salvaged)
368 { 361 {
369 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); 362 try
370 bool salvaged = false;
371 while (!salvaged)
372 { 363 {
373 try 364 m_udpSocket.BeginReceiveFrom(
374 { 365 buf.Data,
375 m_udpSocket.BeginReceiveFrom( 366 0,
376 //wrappedBuffer.Instance.Data, 367 buf.Data.Length,
377 buf.Data, 368 SocketFlags.None,
378 0, 369 ref buf.RemoteEndPoint,
379 UDPPacketBuffer.BUFFER_SIZE, 370 AsyncEndReceive,
380 SocketFlags.None, 371 buf);
381 ref buf.RemoteEndPoint, 372 salvaged = true;
382 AsyncEndReceive,
383 //wrappedBuffer);
384 buf);
385 salvaged = true;
386 }
387 catch (SocketException) { }
388 catch (ObjectDisposedException) { return; }
389 } 373 }
390 374 catch (SocketException) { }
391 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); 375 catch (ObjectDisposedException) { return; }
392 } 376 }
393 } 377
394 catch (ObjectDisposedException e) 378 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
395 {
396 m_log.Error(
397 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
398 }
399 catch (Exception e)
400 {
401 m_log.Error(
402 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
403 } 379 }
404 } 380 }
381 catch (Exception e)
382 {
383 m_log.Error(
384 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
385 }
405 } 386 }
406 387
407 private void AsyncEndReceive(IAsyncResult iar) 388 private void AsyncEndReceive(IAsyncResult iar)
@@ -453,11 +434,6 @@ namespace OpenMetaverse
453 UdpReceives, se.ErrorCode), 434 UdpReceives, se.ErrorCode),
454 se); 435 se);
455 } 436 }
456 catch (ObjectDisposedException e)
457 {
458 m_log.Error(
459 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
460 }
461 catch (Exception e) 437 catch (Exception e)
462 { 438 {
463 m_log.Error( 439 m_log.Error(
@@ -465,14 +441,12 @@ namespace OpenMetaverse
465 } 441 }
466 finally 442 finally
467 { 443 {
468// if (UsePools)
469// Pool.ReturnObject(buffer);
470
471 AsyncBeginReceive(); 444 AsyncBeginReceive();
472 } 445 }
473 } 446 }
474 } 447 }
475 448
449/* not in use
476 public void AsyncBeginSend(UDPPacketBuffer buf) 450 public void AsyncBeginSend(UDPPacketBuffer buf)
477 { 451 {
478// if (IsRunningOutbound) 452// if (IsRunningOutbound)
@@ -511,9 +485,11 @@ namespace OpenMetaverse
511 catch (SocketException) { } 485 catch (SocketException) { }
512 catch (ObjectDisposedException) { } 486 catch (ObjectDisposedException) { }
513 } 487 }
514 488*/
515 public void SyncSend(UDPPacketBuffer buf) 489 public void SyncSend(UDPPacketBuffer buf)
516 { 490 {
491 if(buf.RemoteEndPoint == null)
492 return; // already expired
517 try 493 try
518 { 494 {
519 m_udpSocket.SendTo( 495 m_udpSocket.SendTo(
@@ -527,7 +503,7 @@ namespace OpenMetaverse
527 } 503 }
528 catch (SocketException e) 504 catch (SocketException e)
529 { 505 {
530 m_log.Warn("[UDPBASE]: sync send SocketException {0} " + e.Message); 506 m_log.WarnFormat("[UDPBASE]: sync send SocketException {0} {1}", buf.RemoteEndPoint, e.Message);
531 } 507 }
532 catch (ObjectDisposedException) { } 508 catch (ObjectDisposedException) { }
533 } 509 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index f8ec97a..3277638 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
66 /// </summary> 66 /// </summary>
67 public Int64 MinimumAdaptiveThrottleRate; 67 public Int64 MinimumAdaptiveThrottleRate;
68 68
69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
70 public double CannibalizeTextureRate;
71
72 public int ClientMaxRate; 69 public int ClientMaxRate;
73 public float BrustTime; 70 public float BrustTime;
74 71
@@ -104,12 +101,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
104// AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 101// AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
105 AdaptiveThrottlesEnabled = false; 102 AdaptiveThrottlesEnabled = false;
106 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000); 103 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000);
107
108 // http textures do use udp bandwidth setting
109// CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
110// CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9);
111 CannibalizeTextureRate = 0f;
112
113 } 104 }
114 catch (Exception) { } 105 catch (Exception) { }
115 } 106 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
index 76f4c6f..1f978e1 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
189 // Process all the pending adds 189 // Process all the pending adds
190 OutgoingPacket pendingAdd; 190 OutgoingPacket pendingAdd;
191 while (m_pendingAdds.TryDequeue(out pendingAdd)) 191 while (m_pendingAdds.TryDequeue(out pendingAdd))
192 {
192 if (pendingAdd != null) 193 if (pendingAdd != null)
193 m_packets[pendingAdd.SequenceNumber] = pendingAdd; 194 m_packets[pendingAdd.SequenceNumber] = pendingAdd;
195 }
194 196
195 // Process all the pending removes, including updating statistics and round-trip times 197 // Process all the pending removes, including updating statistics and round-trip times
196 PendingAck pendingAcknowledgement; 198 PendingAck pendingAcknowledgement;
@@ -204,13 +206,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
204 { 206 {
205 m_packets.Remove(pendingAcknowledgement.SequenceNumber); 207 m_packets.Remove(pendingAcknowledgement.SequenceNumber);
206 208
209 // Update stats
210 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
211
212 ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer);
213 ackedPacket.Buffer = null;
214
207 // As with other network applications, assume that an acknowledged packet is an 215 // As with other network applications, assume that an acknowledged packet is an
208 // indication that the network can handle a little more load, speed up the transmission 216 // indication that the network can handle a little more load, speed up the transmission
209 ackedPacket.Client.FlowThrottle.AcknowledgePackets(1); 217 ackedPacket.Client.FlowThrottle.AcknowledgePackets(1);
210 218
211 // Update stats
212 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
213
214 if (!pendingAcknowledgement.FromResend) 219 if (!pendingAcknowledgement.FromResend)
215 { 220 {
216 // Calculate the round-trip time for this packet and its ACK 221 // Calculate the round-trip time for this packet and its ACK
@@ -244,6 +249,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
244 249
245 // Update stats 250 // Update stats
246 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); 251 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
252
253 removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer);
254 removedPacket.Buffer = null;
247 } 255 }
248 } 256 }
249 } 257 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index d36d770..5205576 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
953 return; 953 return;
954 } 954 }
955 955
956 // Saving attachments for NPCs messes them up for the real owner! 956 if(sp.IsNPC)
957 INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); 957 return;
958 if (module != null)
959 {
960 if (module.IsNPC(sp.UUID, m_scene))
961 return;
962 }
963 958
964 if (grp.HasGroupChanged) 959 if (grp.HasGroupChanged)
965 { 960 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index 4e1958a..10bc6aa 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
77 } 77 }
78 78
79 scene.EventManager.OnAvatarKilled += KillAvatar; 79 scene.EventManager.OnAvatarKilled += KillAvatar;
80 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
81 } 80 }
82 81
83 public void RemoveRegion(Scene scene) 82 public void RemoveRegion(Scene scene)
@@ -86,7 +85,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
86 m_scenel.Remove(scene.RegionInfo.RegionHandle); 85 m_scenel.Remove(scene.RegionInfo.RegionHandle);
87 86
88 scene.EventManager.OnAvatarKilled -= KillAvatar; 87 scene.EventManager.OnAvatarKilled -= KillAvatar;
89 scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
90 } 88 }
91 89
92 public void RegionLoaded(Scene scene) 90 public void RegionLoaded(Scene scene)
@@ -177,31 +175,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
177 deadAvatar.setHealthWithUpdate(100.0f); 175 deadAvatar.setHealthWithUpdate(100.0f);
178 deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient); 176 deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient);
179 } 177 }
180
181 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
182 {
183 try
184 {
185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
186 if (obj == null)
187 return;
188 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
189 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
190 {
191 avatar.Invulnerable = false;
192 }
193 else
194 {
195 avatar.Invulnerable = true;
196 if (avatar.Health < 100.0f)
197 {
198 avatar.setHealthWithUpdate(100.0f);
199 }
200 }
201 }
202 catch (Exception)
203 {
204 }
205 }
206 } 178 }
207} 179}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index d6c65a1..69c1e4e 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
526 item.AssetType = (int)AssetType.Object; 526 item.AssetType = (int)AssetType.Object;
527 item.AssetID = asset.FullID; 527 item.AssetID = asset.FullID;
528 528
529 if (DeRezAction.SaveToExistingUserInventoryItem == action) 529 if (action == DeRezAction.SaveToExistingUserInventoryItem)
530 { 530 {
531 m_Scene.InventoryService.UpdateItem(item); 531 m_Scene.InventoryService.UpdateItem(item);
532 } 532 }
533 else 533 else
534 { 534 {
535 AddPermissions(item, objlist[0], objlist, remoteClient); 535 bool isowner = remoteClient != null && item.Owner == remoteClient.AgentId;
536 if(action == DeRezAction.Return)
537 AddPermissions(item, objlist[0], objlist, null);
538 else if(action == DeRezAction.Delete && !isowner)
539 AddPermissions(item, objlist[0], objlist, null);
540 else
541 AddPermissions(item, objlist[0], objlist, remoteClient);
542
536 m_Scene.AddInventoryItem(item); 543 m_Scene.AddInventoryItem(item);
537 544
538 if (remoteClient != null && item.Owner == remoteClient.AgentId) 545 if (isowner)
539 { 546 {
540 remoteClient.SendInventoryItemCreateUpdate(item, 0); 547 remoteClient.SendInventoryItemCreateUpdate(item, 0);
541 } 548 }
@@ -1010,7 +1017,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1010 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); 1017 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
1011 rootPart.ParentGroup.ResumeScripts(); 1018 rootPart.ParentGroup.ResumeScripts();
1012 1019
1013 group.ScheduleGroupForFullUpdate(); 1020 group.ScheduleGroupForFullAnimUpdate();
1014 } 1021 }
1015 else 1022 else
1016 m_Scene.AddNewSceneObject(group, true, false); 1023 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 c3f6d6b..83d91c4 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Concurrent;
30using System.IO; 31using System.IO;
31using System.Net; 32using System.Net;
32using System.Net.Mail; 33using System.Net.Mail;
@@ -94,18 +95,31 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
94 { 95 {
95// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 96// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
96 97
97 private object HttpListLock = new object(); 98 private object m_httpListLock = new object();
98 private int httpTimeout = 30000; 99 private int m_httpTimeout = 30000;
99 private string m_name = "HttpScriptRequests"; 100 private string m_name = "HttpScriptRequests";
100 101
101 private OutboundUrlFilter m_outboundUrlFilter; 102 private OutboundUrlFilter m_outboundUrlFilter;
102 private string m_proxyurl = ""; 103 private string m_proxyurl = "";
103 private string m_proxyexcepts = ""; 104 private string m_proxyexcepts = "";
104 105
106 private float m_primPerSec = 1.0f;
107 private float m_primBurst = 3.0f;
108 private float m_primOwnerPerSec = 25.0f;
109 private float m_primOwnerBurst = 5.0f;
110
111 private struct ThrottleData
112 {
113 public double lastTime;
114 public float count;
115 }
116
105 // <request id, HttpRequestClass> 117 // <request id, HttpRequestClass>
106 private Dictionary<UUID, HttpRequestClass> m_pendingRequests; 118 private Dictionary<UUID, HttpRequestClass> m_pendingRequests;
107 private Scene m_scene; 119 private ConcurrentQueue<HttpRequestClass> m_CompletedRequests;
108 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); 120 private ConcurrentDictionary<uint, ThrottleData> m_RequestsThrottle;
121 private ConcurrentDictionary<UUID, ThrottleData> m_OwnerRequestsThrottle;
122
109 public static SmartThreadPool ThreadPool = null; 123 public static SmartThreadPool ThreadPool = null;
110 124
111 public HttpRequestModule() 125 public HttpRequestModule()
@@ -119,10 +133,77 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
119 return UUID.Zero; 133 return UUID.Zero;
120 } 134 }
121 135
136 public bool CheckThrottle(uint localID, UUID ownerID)
137 {
138 ThrottleData th;
139 double now = Util.GetTimeStamp();
140 bool ret;
141
142 if (m_RequestsThrottle.TryGetValue(localID, out th))
143 {
144 double delta = now - th.lastTime;
145 th.lastTime = now;
146
147 float add = (float)(m_primPerSec * delta);
148 th.count += add;
149 if (th.count > m_primBurst)
150 th.count = m_primBurst;
151
152 ret = th.count > 0;
153 if (ret)
154 th.count--;
155 }
156 else
157 {
158 th = new ThrottleData()
159 {
160 lastTime = now,
161 count = m_primBurst - 1
162 };
163 ret = true;
164 }
165 m_RequestsThrottle[localID] = th;
166
167 if(!ret)
168 return false;
169
170 if (m_OwnerRequestsThrottle.TryGetValue(ownerID, out th))
171 {
172 double delta = now - th.lastTime;
173 th.lastTime = now;
174
175 float add = (float)(m_primOwnerPerSec * delta);
176 th.count += add;
177 if (th.count > m_primOwnerBurst)
178 th.count = m_primOwnerBurst;
179
180 ret = th.count > 0;
181 if (ret)
182 th.count--;
183 }
184 else
185 {
186 th = new ThrottleData()
187 {
188 lastTime = now,
189 count = m_primOwnerBurst - 1
190 };
191 }
192 m_OwnerRequestsThrottle[ownerID] = th;
193
194 return ret;
195 }
196
122 public UUID StartHttpRequest( 197 public UUID StartHttpRequest(
123 uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body, 198 uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body,
124 out HttpInitialRequestStatus status) 199 out HttpInitialRequestStatus status)
125 { 200 {
201 if (!CheckAllowed(new Uri(url)))
202 {
203 status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER;
204 return UUID.Zero;
205 }
206
126 UUID reqID = UUID.Random(); 207 UUID reqID = UUID.Random();
127 HttpRequestClass htc = new HttpRequestClass(); 208 HttpRequestClass htc = new HttpRequestClass();
128 209
@@ -207,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
207 htc.ItemID = itemID; 288 htc.ItemID = itemID;
208 htc.Url = url; 289 htc.Url = url;
209 htc.ReqID = reqID; 290 htc.ReqID = reqID;
210 htc.HttpTimeout = httpTimeout; 291 htc.HttpTimeout = m_httpTimeout;
211 htc.OutboundBody = body; 292 htc.OutboundBody = body;
212 htc.ResponseHeaders = headers; 293 htc.ResponseHeaders = headers;
213 htc.proxyurl = m_proxyurl; 294 htc.proxyurl = m_proxyurl;
@@ -216,16 +297,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
216 // Same number as default HttpWebRequest.MaximumAutomaticRedirections 297 // Same number as default HttpWebRequest.MaximumAutomaticRedirections
217 htc.MaxRedirects = 50; 298 htc.MaxRedirects = 50;
218 299
219 if (StartHttpRequest(htc)) 300 lock (m_httpListLock)
220 { 301 m_pendingRequests.Add(reqID, htc);
221 status = HttpInitialRequestStatus.OK; 302
222 return htc.ReqID; 303 htc.Process();
223 } 304 status = HttpInitialRequestStatus.OK;
224 else 305 return reqID;
225 {
226 status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER;
227 return UUID.Zero;
228 }
229 } 306 }
230 307
231 /// <summary> 308 /// <summary>
@@ -237,34 +314,21 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
237 return m_outboundUrlFilter.CheckAllowed(url); 314 return m_outboundUrlFilter.CheckAllowed(url);
238 } 315 }
239 316
240 public bool StartHttpRequest(HttpRequestClass req)
241 {
242 if (!CheckAllowed(new Uri(req.Url)))
243 return false;
244
245 lock (HttpListLock)
246 {
247 m_pendingRequests.Add(req.ReqID, req);
248 }
249
250 req.Process();
251
252 return true;
253 }
254
255 public void StopHttpRequest(uint m_localID, UUID m_itemID) 317 public void StopHttpRequest(uint m_localID, UUID m_itemID)
256 { 318 {
257 if (m_pendingRequests != null) 319 List<UUID> toremove = new List<UUID>();
320 lock (m_httpListLock)
258 { 321 {
259 lock (HttpListLock) 322 foreach (HttpRequestClass tmpReq in m_pendingRequests.Values)
260 { 323 {
261 HttpRequestClass tmpReq; 324 if(tmpReq.ItemID == m_itemID)
262 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
263 { 325 {
264 tmpReq.Stop(); 326 tmpReq.Stop();
265 m_pendingRequests.Remove(m_itemID); 327 toremove.Add(tmpReq.ReqID);
266 } 328 }
267 } 329 }
330 foreach(UUID id in toremove)
331 m_pendingRequests.Remove(id);
268 } 332 }
269 } 333 }
270 334
@@ -276,37 +340,35 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
276 * finished. I thought about setting up a queue for this, but 340 * finished. I thought about setting up a queue for this, but
277 * it will need some refactoring and this works 'enough' right now 341 * it will need some refactoring and this works 'enough' right now
278 */ 342 */
343 public void GotCompletedRequest(HttpRequestClass req)
344 {
345 lock (m_httpListLock)
346 {
347 if (req.Removed)
348 return;
349 m_pendingRequests.Remove(req.ReqID);
350 m_CompletedRequests.Enqueue(req);
351 }
352 }
279 353
280 public IServiceRequest GetNextCompletedRequest() 354 public IServiceRequest GetNextCompletedRequest()
281 { 355 {
282 lock (HttpListLock) 356 HttpRequestClass req;
283 { 357 if(m_CompletedRequests.TryDequeue(out req))
284 foreach (UUID luid in m_pendingRequests.Keys) 358 return req;
285 {
286 HttpRequestClass tmpReq;
287 359
288 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
289 {
290 if (tmpReq.Finished)
291 {
292 return tmpReq;
293 }
294 }
295 }
296 }
297 return null; 360 return null;
298 } 361 }
299 362
300 public void RemoveCompletedRequest(UUID id) 363 public void RemoveCompletedRequest(UUID reqId)
301 { 364 {
302 lock (HttpListLock) 365 lock (m_httpListLock)
303 { 366 {
304 HttpRequestClass tmpReq; 367 HttpRequestClass tmpReq;
305 if (m_pendingRequests.TryGetValue(id, out tmpReq)) 368 if (m_pendingRequests.TryGetValue(reqId, out tmpReq))
306 { 369 {
307 tmpReq.Stop(); 370 tmpReq.Stop();
308 tmpReq = null; 371 m_pendingRequests.Remove(reqId);
309 m_pendingRequests.Remove(id);
310 } 372 }
311 } 373 }
312 } 374 }
@@ -322,17 +384,28 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
322 384
323 HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384); 385 HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384);
324 386
325
326 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); 387 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
327 int maxThreads = 15;
328 388
329 IConfig httpConfig = config.Configs["HttpRequestModule"]; 389 int maxThreads = 8;
390 IConfig httpConfig = config.Configs["ScriptsHttpRequestModule"];
330 if (httpConfig != null) 391 if (httpConfig != null)
331 { 392 {
332 maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); 393 maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
394 m_primBurst = httpConfig.GetFloat("PrimRequestsBurst", m_primBurst);
395 m_primPerSec = httpConfig.GetFloat("PrimRequestsPerSec", m_primPerSec);
396 m_primOwnerBurst = httpConfig.GetFloat("PrimOwnerRequestsBurst", m_primOwnerBurst);
397 m_primOwnerPerSec = httpConfig.GetFloat("PrimOwnerRequestsPerSec", m_primOwnerPerSec);
398 m_httpTimeout = httpConfig.GetInt("RequestsTimeOut", m_httpTimeout);
399 if(m_httpTimeout > 60000)
400 m_httpTimeout = 60000;
401 else if(m_httpTimeout < 200)
402 m_httpTimeout = 200;
333 } 403 }
334 404
335 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 405 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
406 m_CompletedRequests = new ConcurrentQueue<HttpRequestClass>();
407 m_RequestsThrottle = new ConcurrentDictionary<uint, ThrottleData>();
408 m_OwnerRequestsThrottle = new ConcurrentDictionary<UUID, ThrottleData>();
336 409
337 // First instance sets this up for all sims 410 // First instance sets this up for all sims
338 if (ThreadPool == null) 411 if (ThreadPool == null)
@@ -352,16 +425,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
352 425
353 public void AddRegion(Scene scene) 426 public void AddRegion(Scene scene)
354 { 427 {
355 m_scene = scene; 428 scene.RegisterModuleInterface<IHttpRequestModule>(this);
356
357 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
358 } 429 }
359 430
360 public void RemoveRegion(Scene scene) 431 public void RemoveRegion(Scene scene)
361 { 432 {
362 scene.UnregisterModuleInterface<IHttpRequestModule>(this); 433 scene.UnregisterModuleInterface<IHttpRequestModule>(this);
363 if (scene == m_scene)
364 m_scene = null;
365 } 434 }
366 435
367 public void PostInitialise() 436 public void PostInitialise()
@@ -406,11 +475,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
406 /// </summary> 475 /// </summary>
407 public HttpRequestModule RequestModule { get; set; } 476 public HttpRequestModule RequestModule { get; set; }
408 477
409 private bool _finished; 478 public bool Finished { get; private set;}
410 public bool Finished 479 public bool Removed{ get; set;}
411 {
412 get { return _finished; }
413 }
414 480
415 public static int HttpBodyMaxLenMAX = 16384; 481 public static int HttpBodyMaxLenMAX = 16384;
416 482
@@ -427,19 +493,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
427 public bool HttpPragmaNoCache = true; 493 public bool HttpPragmaNoCache = true;
428 494
429 // Request info 495 // Request info
430 private UUID _itemID; 496 public UUID ReqID { get; set; }
431 public UUID ItemID 497 public UUID ItemID { get; set;}
432 { 498 public uint LocalID { get; set;}
433 get { return _itemID; } 499
434 set { _itemID = value; }
435 }
436 private uint _localID;
437 public uint LocalID
438 {
439 get { return _localID; }
440 set { _localID = value; }
441 }
442 public DateTime Next;
443 public string proxyurl; 500 public string proxyurl;
444 public string proxyexcepts; 501 public string proxyexcepts;
445 502
@@ -454,12 +511,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
454 public int MaxRedirects { get; set; } 511 public int MaxRedirects { get; set; }
455 512
456 public string OutboundBody; 513 public string OutboundBody;
457 private UUID _reqID; 514
458 public UUID ReqID
459 {
460 get { return _reqID; }
461 set { _reqID = value; }
462 }
463 public HttpWebRequest Request; 515 public HttpWebRequest Request;
464 public string ResponseBody; 516 public string ResponseBody;
465 public List<string> ResponseMetadata; 517 public List<string> ResponseMetadata;
@@ -469,10 +521,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
469 521
470 public void Process() 522 public void Process()
471 { 523 {
472 _finished = false; 524 WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
473
474 lock (HttpRequestModule.ThreadPool)
475 WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
476 } 525 }
477 526
478 private object StpSendWrapper(object o) 527 private object StpSendWrapper(object o)
@@ -521,6 +570,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
521 570
522 public void SendRequest() 571 public void SendRequest()
523 { 572 {
573 if(Removed)
574 return;
575
524 HttpWebResponse response = null; 576 HttpWebResponse response = null;
525 Stream resStream = null; 577 Stream resStream = null;
526 byte[] buf = new byte[HttpBodyMaxLenMAX + 16]; 578 byte[] buf = new byte[HttpBodyMaxLenMAX + 16];
@@ -534,6 +586,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
534 586
535 Request.AllowAutoRedirect = false; 587 Request.AllowAutoRedirect = false;
536 Request.KeepAlive = false; 588 Request.KeepAlive = false;
589 Request.Timeout = HttpTimeout;
537 590
538 //This works around some buggy HTTP Servers like Lighttpd 591 //This works around some buggy HTTP Servers like Lighttpd
539 Request.ServicePoint.Expect100Continue = false; 592 Request.ServicePoint.Expect100Continue = false;
@@ -593,7 +646,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
593 bstream.Write(data, 0, data.Length); 646 bstream.Write(data, 0, data.Length);
594 } 647 }
595 648
596 Request.Timeout = HttpTimeout;
597 try 649 try
598 { 650 {
599 // execute the request 651 // execute the request
@@ -672,7 +724,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
672 if (response != null) 724 if (response != null)
673 response.Close(); 725 response.Close();
674 726
675
676 // We need to resubmit 727 // We need to resubmit
677 if ( 728 if (
678 (Status == (int)HttpStatusCode.MovedPermanently 729 (Status == (int)HttpStatusCode.MovedPermanently
@@ -684,7 +735,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
684 { 735 {
685 Status = (int)OSHttpStatusCode.ClientErrorJoker; 736 Status = (int)OSHttpStatusCode.ClientErrorJoker;
686 ResponseBody = "Number of redirects exceeded max redirects"; 737 ResponseBody = "Number of redirects exceeded max redirects";
687 _finished = true; 738 WorkItem = null;
739 RequestModule.GotCompletedRequest(this);
688 } 740 }
689 else 741 else
690 { 742 {
@@ -694,13 +746,15 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
694 { 746 {
695 Status = (int)OSHttpStatusCode.ClientErrorJoker; 747 Status = (int)OSHttpStatusCode.ClientErrorJoker;
696 ResponseBody = "HTTP redirect code but no location header"; 748 ResponseBody = "HTTP redirect code but no location header";
697 _finished = true; 749 WorkItem = null;
750 RequestModule.GotCompletedRequest(this);
698 } 751 }
699 else if (!RequestModule.CheckAllowed(new Uri(location))) 752 else if (!RequestModule.CheckAllowed(new Uri(location)))
700 { 753 {
701 Status = (int)OSHttpStatusCode.ClientErrorJoker; 754 Status = (int)OSHttpStatusCode.ClientErrorJoker;
702 ResponseBody = "URL from HTTP redirect blocked: " + location; 755 ResponseBody = "URL from HTTP redirect blocked: " + location;
703 _finished = true; 756 WorkItem = null;
757 RequestModule.GotCompletedRequest(this);
704 } 758 }
705 else 759 else
706 { 760 {
@@ -717,9 +771,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
717 } 771 }
718 else 772 else
719 { 773 {
720 _finished = true; 774 WorkItem = null;
721 if (ResponseBody == null) 775 if (ResponseBody == null)
722 ResponseBody = String.Empty; 776 ResponseBody = String.Empty;
777 RequestModule.GotCompletedRequest(this);
723 } 778 }
724 } 779 }
725 } 780 }
@@ -728,10 +783,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
728 { 783 {
729 try 784 try
730 { 785 {
786 Removed = true;
787 if(WorkItem == null)
788 return;
789
731 if (!WorkItem.Cancel()) 790 if (!WorkItem.Cancel())
732 {
733 WorkItem.Cancel(true); 791 WorkItem.Cancel(true);
734 }
735 } 792 }
736 catch (Exception) 793 catch (Exception)
737 { 794 {
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 2e801e3..ac28cee 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
1204 } 1204 }
1205 } 1205 }
1206 1206
1207 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) 1207 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey, bool kick)
1208 { 1208 {
1209 if (prey == UUID.Zero)
1210 return;
1211
1209 EstateTeleportOneUserHomeRequest evOverride = OnEstateTeleportOneUserHomeRequest; 1212 EstateTeleportOneUserHomeRequest evOverride = OnEstateTeleportOneUserHomeRequest;
1210 if(evOverride != null) 1213 if(evOverride != null)
1211 { 1214 {
1212 evOverride(remover_client, invoice, senderID, prey); 1215 evOverride(remover_client, invoice, senderID, prey, kick);
1213 return; 1216 return;
1214 } 1217 }
1215 1218
1216 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) 1219 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false))
1217 return; 1220 return;
1218 1221
1219 if (prey != UUID.Zero) 1222 ScenePresence s = Scene.GetScenePresence(prey);
1223 if (s != null && !s.IsDeleted && !s.IsInTransit)
1220 { 1224 {
1221 ScenePresence s = Scene.GetScenePresence(prey); 1225 if (kick)
1222 if (s != null && !s.IsDeleted && !s.IsInTransit)
1223 { 1226 {
1224 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 1227 s.ControllingClient.Kick("You have been kicked");
1225 { 1228 Scene.CloseAgent(s.UUID, false);
1226 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 1229 }
1227 Scene.CloseAgent(s.UUID, false); 1230 else if (!Scene.TeleportClientHome(prey, s.ControllingClient))
1228 } 1231 {
1232 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed ");
1233 Scene.CloseAgent(s.UUID, false);
1229 } 1234 }
1230 } 1235 }
1231 } 1236 }
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
index f4a174a..c8b9032 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
204 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message); 204 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message);
205 } 205 }
206 206
207 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey) 207 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey, bool kick)
208 { 208 {
209 if (prey == UUID.Zero) 209 if (prey == UUID.Zero)
210 return; 210 return;
@@ -227,8 +227,20 @@ namespace OpenSim.Region.CoreModules.World.Estate
227 ScenePresence p = scene.GetScenePresence(prey); 227 ScenePresence p = scene.GetScenePresence(prey);
228 if (p != null && !p.IsChildAgent && !p.IsDeleted && !p.IsInTransit) 228 if (p != null && !p.IsChildAgent && !p.IsDeleted && !p.IsInTransit)
229 { 229 {
230 p.ControllingClient.SendTeleportStart(16); 230 if (kick)
231 scene.TeleportClientHome(prey, client); 231 {
232 p.ControllingClient.Kick("You have been kicked out");
233 s.CloseAgent(p.UUID, false);
234 }
235 else
236 {
237 p.ControllingClient.SendTeleportStart(16);
238 if (!s.TeleportClientHome(prey, client))
239 {
240 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed");
241 s.CloseAgent(p.UUID, false);
242 }
243 }
232 return; 244 return;
233 } 245 }
234 } 246 }
@@ -259,6 +271,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
259 { 271 {
260 p.ControllingClient.SendTeleportStart(16); 272 p.ControllingClient.SendTeleportStart(16);
261 scene.TeleportClientHome(p.ControllingClient.AgentId, client); 273 scene.TeleportClientHome(p.ControllingClient.AgentId, client);
274 if (!s.TeleportClientHome(p.ControllingClient.AgentId, client))
275 {
276 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
277 s.CloseAgent(p.UUID, false);
278 }
262 } 279 }
263 }); 280 });
264 } 281 }
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index 978c248..2c75844 100644
--- a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
+++ b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
@@ -87,5 +87,6 @@ namespace OpenSim.Region.Framework.Interfaces
87 void StopHttpRequest(uint m_localID, UUID m_itemID); 87 void StopHttpRequest(uint m_localID, UUID m_itemID);
88 IServiceRequest GetNextCompletedRequest(); 88 IServiceRequest GetNextCompletedRequest();
89 void RemoveCompletedRequest(UUID id); 89 void RemoveCompletedRequest(UUID id);
90 bool CheckThrottle(uint localID, UUID onerID);
90 } 91 }
91} 92}
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 7509686..eae6d6f 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -94,19 +94,15 @@ namespace OpenSim.Region.Framework.Scenes
94 m_inventoryDeletes.Enqueue(dtis); 94 m_inventoryDeletes.Enqueue(dtis);
95 } 95 }
96 96
97 if (Enabled)
98 lock (m_inventoryTicker)
99 m_inventoryTicker.Start();
100
101 // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object
102 // has gone to inventory, it will reappear in the region again on restart instead of being lost.
103 // This is not ideal since the object will still be available for manipulation when it should be, but it's
104 // better than losing the object for now.
105 if (permissionToDelete) 97 if (permissionToDelete)
106 { 98 {
107 foreach (SceneObjectGroup g in objectGroups) 99 foreach (SceneObjectGroup g in objectGroups)
108 g.DeleteGroupFromScene(false); 100 g.DeleteGroupFromScene(false);
109 } 101 }
102
103 if (Enabled)
104 lock (m_inventoryTicker)
105 m_inventoryTicker.Start();
110 } 106 }
111 107
112 private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) 108 private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index f76f882..edc8886 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -539,7 +539,7 @@ namespace OpenSim.Region.Framework.Scenes
539 /// <see cref="SceneObjectPart.TriggerScriptChangedEvent"/> 539 /// <see cref="SceneObjectPart.TriggerScriptChangedEvent"/>
540 /// </remarks> 540 /// </remarks>
541 public event ScriptChangedEvent OnScriptChangedEvent; 541 public event ScriptChangedEvent OnScriptChangedEvent;
542 public delegate void ScriptChangedEvent(uint localID, uint change); 542 public delegate void ScriptChangedEvent(uint localID, uint change, object data);
543 543
544 public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); 544 public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed);
545 545
@@ -1185,7 +1185,7 @@ namespace OpenSim.Region.Framework.Scenes
1185 } 1185 }
1186 } 1186 }
1187 1187
1188 public void TriggerOnScriptChangedEvent(uint localID, uint change) 1188 public void TriggerOnScriptChangedEvent(uint localID, uint change, object parameter = null)
1189 { 1189 {
1190 ScriptChangedEvent handlerScriptChangedEvent = OnScriptChangedEvent; 1190 ScriptChangedEvent handlerScriptChangedEvent = OnScriptChangedEvent;
1191 if (handlerScriptChangedEvent != null) 1191 if (handlerScriptChangedEvent != null)
@@ -1194,7 +1194,7 @@ namespace OpenSim.Region.Framework.Scenes
1194 { 1194 {
1195 try 1195 try
1196 { 1196 {
1197 d(localID, change); 1197 d(localID, change, parameter);
1198 } 1198 }
1199 catch (Exception e) 1199 catch (Exception e)
1200 { 1200 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index e6e0354..debcad3 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
2110 // build a list of eligible objects 2110 // build a list of eligible objects
2111 List<uint> deleteIDs = new List<uint>(); 2111 List<uint> deleteIDs = new List<uint>();
2112 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 2112 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
2113 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>(); 2113 List<SceneObjectGroup> takeCopyGroups = new List<SceneObjectGroup>();
2114 List<SceneObjectGroup> takeDeleteGroups = new List<SceneObjectGroup>(); 2114 List<SceneObjectGroup> takeDeleteGroups = new List<SceneObjectGroup>();
2115 2115
2116 ScenePresence sp = null; 2116 ScenePresence sp = null;
@@ -2119,11 +2119,10 @@ namespace OpenSim.Region.Framework.Scenes
2119 else if(action != DeRezAction.Return) 2119 else if(action != DeRezAction.Return)
2120 return; // only Return can be called without a client 2120 return; // only Return can be called without a client
2121 2121
2122 // Start with true for both, then remove the flags if objects 2122 // this is not as 0.8x code
2123 // that we can't derez are part of the selection 2123 // 0.8x did refuse all operation is not allowed on all objects
2124 bool permissionToTake = true; 2124 // this will do it on allowed objects
2125 bool permissionToTakeCopy = true; 2125 // current viewers only ask if all allowed
2126 bool permissionToDelete = true;
2127 2126
2128 foreach (uint localID in localIDs) 2127 foreach (uint localID in localIDs)
2129 { 2128 {
@@ -2136,8 +2135,8 @@ namespace OpenSim.Region.Framework.Scenes
2136 continue; 2135 continue;
2137 } 2136 }
2138 2137
2139 // Already deleted by someone else 2138 SceneObjectGroup grp = part.ParentGroup;
2140 if (part.ParentGroup.IsDeleted) 2139 if (grp == null || grp.IsDeleted)
2141 { 2140 {
2142 //Client still thinks the object exists, kill it 2141 //Client still thinks the object exists, kill it
2143 deleteIDs.Add(localID); 2142 deleteIDs.Add(localID);
@@ -2145,132 +2144,105 @@ namespace OpenSim.Region.Framework.Scenes
2145 } 2144 }
2146 2145
2147 // Can't delete child prims 2146 // Can't delete child prims
2148 if (part != part.ParentGroup.RootPart) 2147 if (part != grp.RootPart)
2149 continue; 2148 continue;
2150 2149
2151 SceneObjectGroup grp = part.ParentGroup;
2152 if (grp.IsAttachment) 2150 if (grp.IsAttachment)
2153 continue; 2151 {
2152 if(!sp.IsGod || action != DeRezAction.Return || action != DeRezAction.Delete)
2153 continue;
2154 // this may break the attachment, but its a security action
2155 // viewers don't allow it anyways
2156 }
2154 2157
2155 // If child prims have invalid perms, fix them 2158 // If child prims have invalid perms, fix them
2156 grp.AdjustChildPrimPermissions(false); 2159 grp.AdjustChildPrimPermissions(false);
2157 2160
2158 if (remoteClient == null) 2161 switch (action)
2159 { 2162 {
2160 // Autoreturn has a null client. Nothing else does. So 2163 case DeRezAction.SaveToExistingUserInventoryItem:
2161 // allow only returns
2162 if (action != DeRezAction.Return)
2163 { 2164 {
2164 m_log.WarnFormat( 2165 if (Permissions.CanTakeCopyObject(grp, sp))
2165 "[AGENT INVENTORY]: Ignoring attempt to {0} {1} {2} without a client", 2166 takeCopyGroups.Add(grp);
2166 action, grp.Name, grp.UUID); 2167 break;
2167 return;
2168 } 2168 }
2169 2169
2170 permissionToTakeCopy = false; 2170 case DeRezAction.TakeCopy:
2171 }
2172 else
2173 {
2174 if (action == DeRezAction.TakeCopy)
2175 { 2171 {
2176 if (!Permissions.CanTakeCopyObject(grp, sp)) 2172 if (Permissions.CanTakeCopyObject(grp, sp))
2177 permissionToTakeCopy = false; 2173 takeCopyGroups.Add(grp);
2174 break;
2178 } 2175 }
2179 else 2176
2177 case DeRezAction.Take:
2180 { 2178 {
2181 permissionToTakeCopy = false; 2179 if (Permissions.CanTakeObject(grp, sp))
2180 takeDeleteGroups.Add(grp);
2181 break;
2182 } 2182 }
2183 if (!Permissions.CanTakeObject(grp, sp))
2184 permissionToTake = false;
2185
2186 if (!Permissions.CanDeleteObject(grp, remoteClient))
2187 permissionToDelete = false;
2188 }
2189
2190 // Handle god perms
2191 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
2192 {
2193 permissionToTake = true;
2194 permissionToTakeCopy = true;
2195 permissionToDelete = true;
2196 }
2197
2198 // If we're re-saving, we don't even want to delete
2199 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2200 permissionToDelete = false;
2201 2183
2202 // if we want to take a copy, we also don't want to delete 2184 case DeRezAction.GodTakeCopy:
2203 // Note: after this point, the permissionToTakeCopy flag
2204 // becomes irrelevant. It already includes the permissionToTake
2205 // permission and after excluding no copy items here, we can
2206 // just use that.
2207 if (action == DeRezAction.TakeCopy)
2208 {
2209 // If we don't have permission, stop right here
2210 if (!permissionToTakeCopy)
2211 { 2185 {
2212 remoteClient.SendAlertMessage("You don't have permission to take the object"); 2186 if((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
2213 return; 2187 takeCopyGroups.Add(grp);
2188 break;
2214 } 2189 }
2215 2190
2216 permissionToTake = true; 2191 case DeRezAction.Delete:
2217 // Don't delete
2218 permissionToDelete = false;
2219 }
2220
2221 if (action == DeRezAction.Return)
2222 {
2223 if (remoteClient != null)
2224 { 2192 {
2225 if (Permissions.CanReturnObjects( 2193 if (Permissions.CanDeleteObject(grp, remoteClient))
2226 null,
2227 remoteClient,
2228 new List<SceneObjectGroup>() {grp}))
2229 { 2194 {
2230 permissionToTake = true; 2195 if(m_useTrashOnDelete || (sp.IsGod && grp.OwnerID != sp.UUID))
2231 permissionToDelete = true; 2196 takeDeleteGroups.Add(grp);
2232 if(AddToReturns) 2197 else
2233 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, 2198 deleteGroups.Add(grp);
2234 "parcel owner return");
2235 } 2199 }
2200 break;
2236 } 2201 }
2237 else // Auto return passes through here with null agent 2202
2203 case DeRezAction.Return:
2238 { 2204 {
2239 permissionToTake = true; 2205 if (remoteClient != null)
2240 permissionToDelete = true; 2206 {
2207 if (Permissions.CanReturnObjects( null, remoteClient, new List<SceneObjectGroup>() {grp}))
2208 {
2209 takeDeleteGroups.Add(grp);
2210 if (AddToReturns)
2211 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition,
2212 "parcel owner return");
2213 }
2214 }
2215 else // Auto return passes through here with null agent
2216 {
2217 takeDeleteGroups.Add(grp);
2218 }
2219 break;
2241 } 2220 }
2242 }
2243 2221
2244 if (permissionToDelete) 2222 default:
2245 { 2223 break;
2246 if (permissionToTake)
2247 takeDeleteGroups.Add(grp);
2248 else
2249 deleteGroups.Add(grp);
2250 deleteIDs.Add(grp.LocalId);
2251 } 2224 }
2252 else if(permissionToTake)
2253 takeGroups.Add(grp);
2254 } 2225 }
2255 2226
2256 SendKillObject(deleteIDs); 2227 if(deleteIDs.Count > 0)
2228 SendKillObject(deleteIDs);
2257 2229
2258 if (takeDeleteGroups.Count > 0) 2230 if (takeDeleteGroups.Count > 0)
2259 { 2231 {
2260 m_asyncSceneObjectDeleter.DeleteToInventory( 2232 m_asyncSceneObjectDeleter.DeleteToInventory(action, destinationID, takeDeleteGroups,
2261 action, destinationID, takeDeleteGroups, remoteClient, 2233 remoteClient, true);
2262 true);
2263 } 2234 }
2264 if (takeGroups.Count > 0) 2235
2236 if (takeCopyGroups.Count > 0)
2265 { 2237 {
2266 m_asyncSceneObjectDeleter.DeleteToInventory( 2238 m_asyncSceneObjectDeleter.DeleteToInventory(action, destinationID, takeCopyGroups,
2267 action, destinationID, takeGroups, remoteClient, 2239 remoteClient, false);
2268 false);
2269 } 2240 }
2241
2270 if (deleteGroups.Count > 0) 2242 if (deleteGroups.Count > 0)
2271 { 2243 {
2272 foreach (SceneObjectGroup g in deleteGroups) 2244 foreach (SceneObjectGroup g in deleteGroups)
2273 DeleteSceneObject(g, true); 2245 DeleteSceneObject(g, false);
2274 } 2246 }
2275 } 2247 }
2276 2248
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index b526fe9..ea037be 100755
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1913,9 +1913,8 @@ namespace OpenSim.Region.Framework.Scenes
1913 { 1913 {
1914 if (parentGroup.OwnerID == child.OwnerID) 1914 if (parentGroup.OwnerID == child.OwnerID)
1915 { 1915 {
1916 parentGroup.LinkToGroup(child);
1917
1918 child.DetachFromBackup(); 1916 child.DetachFromBackup();
1917 parentGroup.LinkToGroup(child);
1919 1918
1920 // this is here so physics gets updated! 1919 // this is here so physics gets updated!
1921 // Don't remove! Bad juju! Stay away! or fix physics! 1920 // Don't remove! Bad juju! Stay away! or fix physics!
@@ -1943,7 +1942,6 @@ namespace OpenSim.Region.Framework.Scenes
1943*/ 1942*/
1944 parentGroup.AdjustChildPrimPermissions(false); 1943 parentGroup.AdjustChildPrimPermissions(false);
1945 parentGroup.HasGroupChanged = true; 1944 parentGroup.HasGroupChanged = true;
1946 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1947 parentGroup.ScheduleGroupForFullAnimUpdate(); 1945 parentGroup.ScheduleGroupForFullAnimUpdate();
1948 Monitor.Exit(m_linkLock); 1946 Monitor.Exit(m_linkLock);
1949 } 1947 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index bf217a5..8899e96 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
154 // We're adding this to a prim we don't own. Force 154 // We're adding this to a prim we don't own. Force
155 // owner change 155 // owner change
156 taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 156 taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
157 157 taskItem.LastOwnerID = item.Owner;
158 } 158 }
159 else 159 else
160 { 160 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index a23ebbf..312ce26 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -3242,8 +3242,6 @@ namespace OpenSim.Region.Framework.Scenes
3242 if (ParentGroup.Scene.GetNumberOfClients() == 0) 3242 if (ParentGroup.Scene.GetNumberOfClients() == 0)
3243 return; 3243 return;
3244 3244
3245 ParentGroup.QueueForUpdateCheck();
3246
3247 bool isfull = false; 3245 bool isfull = false;
3248 if (ParentGroup.IsAttachment) 3246 if (ParentGroup.IsAttachment)
3249 { 3247 {
@@ -3254,6 +3252,8 @@ namespace OpenSim.Region.Framework.Scenes
3254 lock (UpdateFlagLock) 3252 lock (UpdateFlagLock)
3255 UpdateFlag |= update; 3253 UpdateFlag |= update;
3256 3254
3255 ParentGroup.QueueForUpdateCheck();
3256
3257 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull); 3257 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull);
3258 } 3258 }
3259 3259
@@ -4439,10 +4439,10 @@ namespace OpenSim.Region.Framework.Scenes
4439 SceneObjectSerializer.SOPToXml2(xmlWriter, this, new Dictionary<string, object>()); 4439 SceneObjectSerializer.SOPToXml2(xmlWriter, this, new Dictionary<string, object>());
4440 } 4440 }
4441 4441
4442 public void TriggerScriptChangedEvent(Changed val) 4442 public void TriggerScriptChangedEvent(Changed val, object data = null)
4443 { 4443 {
4444 if (ParentGroup != null && ParentGroup.Scene != null) 4444 if (ParentGroup != null && ParentGroup.Scene != null)
4445 ParentGroup.Scene.EventManager.TriggerOnScriptChangedEvent(LocalId, (uint)val); 4445 ParentGroup.Scene.EventManager.TriggerOnScriptChangedEvent(LocalId, (uint)val, data);
4446 } 4446 }
4447 4447
4448 public void TrimPermissions() 4448 public void TrimPermissions()
@@ -5130,11 +5130,10 @@ namespace OpenSim.Region.Framework.Scenes
5130 5130
5131 if (changeFlags == 0) 5131 if (changeFlags == 0)
5132 return; 5132 return;
5133 m_shape.TextureEntry = newTex.GetBytes(); 5133 m_shape.TextureEntry = newTex.GetBytes(9);
5134 TriggerScriptChangedEvent(changeFlags); 5134 TriggerScriptChangedEvent(changeFlags);
5135 ParentGroup.HasGroupChanged = true; 5135 ParentGroup.HasGroupChanged = true;
5136 ScheduleFullUpdate(); 5136 ScheduleUpdate(PrimUpdateFlags.Textures);
5137
5138 } 5137 }
5139 5138
5140 /// <summary> 5139 /// <summary>
@@ -5160,10 +5159,10 @@ namespace OpenSim.Region.Framework.Scenes
5160 if (changeFlags == 0) 5159 if (changeFlags == 0)
5161 return; 5160 return;
5162 5161
5163 m_shape.TextureEntry = newTex.GetBytes(); 5162 m_shape.TextureEntry = newTex.GetBytes(9);
5164 TriggerScriptChangedEvent(changeFlags); 5163 TriggerScriptChangedEvent(changeFlags);
5165 ParentGroup.HasGroupChanged = true; 5164 ParentGroup.HasGroupChanged = true;
5166 ScheduleFullUpdate(); 5165 ScheduleUpdate(PrimUpdateFlags.Textures);
5167 } 5166 }
5168 5167
5169 internal void UpdatePhysicsSubscribedEvents() 5168 internal void UpdatePhysicsSubscribedEvents()
@@ -5575,20 +5574,26 @@ namespace OpenSim.Region.Framework.Scenes
5575 // handle osVolumeDetect 5574 // handle osVolumeDetect
5576 public void ScriptSetVolumeDetect(bool makeVolumeDetect) 5575 public void ScriptSetVolumeDetect(bool makeVolumeDetect)
5577 { 5576 {
5577 if(ParentGroup.IsDeleted)
5578 return;
5579
5578 if(_parentID == 0) 5580 if(_parentID == 0)
5579 { 5581 {
5580 // if root prim do it via SOG 5582 // if root prim do it is like llVolumeDetect
5581 ParentGroup.ScriptSetVolumeDetect(makeVolumeDetect); 5583 ParentGroup.ScriptSetVolumeDetect(makeVolumeDetect);
5582 return; 5584 return;
5583 } 5585 }
5584 5586
5585 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 5587 if(ParentGroup.IsVolumeDetect)
5586 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 5588 return; // entire linkset is phantom already
5587 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 5589
5590 bool wasUsingPhysics = ParentGroup.UsesPhysics;
5591 bool wasTemporary = ParentGroup.IsTemporary;
5592 bool wasPhantom = ParentGroup.IsPhantom;
5588 5593
5589 if(PhysActor != null) 5594 if(PhysActor != null)
5590 PhysActor.Building = true; 5595 PhysActor.Building = true;
5591 UpdatePrimFlags(wasUsingPhysics,wasTemporary,wasPhantom,makeVolumeDetect,false); 5596 UpdatePrimFlags(wasUsingPhysics, wasTemporary, wasPhantom, makeVolumeDetect, false);
5592 } 5597 }
5593 5598
5594 protected static int m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0x5fffafL); 5599 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 4934b83..a0f8959 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -815,10 +815,10 @@ namespace OpenSim.Region.Framework.Scenes
815 m_items.LockItemsForWrite(true); 815 m_items.LockItemsForWrite(true);
816 m_items.Add(item.ItemID, item); 816 m_items.Add(item.ItemID, item);
817 m_items.LockItemsForWrite(false); 817 m_items.LockItemsForWrite(false);
818 if (allowedDrop) 818 if (allowedDrop)
819 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 819 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP, item.ItemID);
820 else 820 else
821 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 821 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
822 822
823 m_part.AggregateInnerPerms(); 823 m_part.AggregateInnerPerms();
824 m_inventorySerial++; 824 m_inventorySerial++;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cfb1be4..1c5d23d 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -507,7 +507,19 @@ namespace OpenSim.Region.Framework.Scenes
507 /// <summary> 507 /// <summary>
508 /// Physical scene representation of this Avatar. 508 /// Physical scene representation of this Avatar.
509 /// </summary> 509 /// </summary>
510 public PhysicsActor PhysicsActor { get; private set; } 510
511 PhysicsActor m_physActor;
512 public PhysicsActor PhysicsActor
513 {
514 get
515 {
516 return m_physActor;
517 }
518 private set
519 {
520 m_physActor = value;
521 }
522 }
511 523
512 /// <summary> 524 /// <summary>
513 /// Record user movement inputs. 525 /// Record user movement inputs.
@@ -523,7 +535,12 @@ namespace OpenSim.Region.Framework.Scenes
523 535
524 public bool Invulnerable 536 public bool Invulnerable
525 { 537 {
526 set { m_invulnerable = value; } 538 set
539 {
540 m_invulnerable = value;
541 if(value && Health != 100.0f)
542 Health = 100.0f;
543 }
527 get { return m_invulnerable; } 544 get { return m_invulnerable; }
528 } 545 }
529 546
@@ -1636,15 +1653,15 @@ namespace OpenSim.Region.Framework.Scenes
1636 /// </summary> 1653 /// </summary>
1637 public void RemoveFromPhysicalScene() 1654 public void RemoveFromPhysicalScene()
1638 { 1655 {
1639 if (PhysicsActor != null) 1656 PhysicsActor pa = Interlocked.Exchange(ref m_physActor, null);
1657 if (pa != null)
1640 { 1658 {
1641// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1659// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1642 1660
1643 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1661 pa.OnOutOfBounds -= OutOfBoundsCall;
1644 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1662 pa.OnCollisionUpdate -= PhysicsCollisionUpdate;
1645 PhysicsActor.UnSubscribeEvents(); 1663 pa.UnSubscribeEvents();
1646 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1664 m_scene.PhysicsScene.RemoveAvatar(pa);
1647 PhysicsActor = null;
1648 } 1665 }
1649// else 1666// else
1650// { 1667// {
@@ -2537,7 +2554,7 @@ namespace OpenSim.Region.Framework.Scenes
2537 m_pos.X = 127f; 2554 m_pos.X = 127f;
2538 m_pos.Y = 127f; 2555 m_pos.Y = 127f;
2539 m_pos.Z = 127f; 2556 m_pos.Z = 127f;
2540 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); 2557 m_log.Error("[AVATAR]: NonFinite Avatar on lastFiniteposition also. Reset Position. Mantis this please. Error #9999903");
2541 } 2558 }
2542 2559
2543 if(isphysical) 2560 if(isphysical)
@@ -5007,16 +5024,17 @@ namespace OpenSim.Region.Framework.Scenes
5007 PhysicsScene scene = m_scene.PhysicsScene; 5024 PhysicsScene scene = m_scene.PhysicsScene;
5008 Vector3 pVec = AbsolutePosition; 5025 Vector3 pVec = AbsolutePosition;
5009 5026
5010 PhysicsActor = scene.AddAvatar( 5027 PhysicsActor pa = scene.AddAvatar(
5011 LocalId, Firstname + "." + Lastname, pVec, 5028 LocalId, Firstname + "." + Lastname, pVec,
5012 Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying); 5029 Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying);
5013 PhysicsActor.Orientation = m_bodyRot; 5030 pa.Orientation = m_bodyRot;
5014 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 5031 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
5015 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 5032 pa.OnCollisionUpdate += PhysicsCollisionUpdate;
5016 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 5033 pa.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
5017 PhysicsActor.SubscribeEvents(100); 5034 pa.SubscribeEvents(100);
5018 PhysicsActor.LocalID = LocalId; 5035 pa.LocalID = LocalId;
5019 PhysicsActor.SetAlwaysRun = m_setAlwaysRun; 5036 pa.SetAlwaysRun = m_setAlwaysRun;
5037 PhysicsActor = pa;
5020 } 5038 }
5021 5039
5022 private void OutOfBoundsCall(Vector3 pos) 5040 private void OutOfBoundsCall(Vector3 pos)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index a60381a..020c7be 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
155 return iout; 155 return iout;
156 } 156 }
157 157
158/*
158 // new using terrain data and patchs indexes 159 // new using terrain data and patchs indexes
159 public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] map) 160 public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] map)
160 { 161 {
@@ -213,6 +214,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
213 214
214 return ret; 215 return ret;
215 } 216 }
217*/
216 218
217 public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY) 219 public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
218 { 220 {
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index 516f9eb..822439f 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -323,7 +323,7 @@ namespace OpenSim.Region.OptionalModules.Materials
323 } 323 }
324 324
325 if(facechanged) 325 if(facechanged)
326 part.Shape.TextureEntry = te.GetBytes(); 326 part.Shape.TextureEntry = te.GetBytes(9);
327 327
328 if(facechanged || partchanged) 328 if(facechanged || partchanged)
329 { 329 {
@@ -632,7 +632,7 @@ namespace OpenSim.Region.OptionalModules.Materials
632 faceEntry.MaterialID = id; 632 faceEntry.MaterialID = id;
633 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id); 633 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
634 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually 634 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
635 sop.Shape.TextureEntry = te.GetBytes(); 635 sop.Shape.TextureEntry = te.GetBytes(9);
636 } 636 }
637 637
638 if(oldid != UUID.Zero) 638 if(oldid != UUID.Zero)
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs b/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs
index 40c6b98..4e9216d 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSActorAvatarMove.cs
@@ -47,9 +47,9 @@ public class BSActorAvatarMove : BSActor
47 // The amount the step up is applying. Used to smooth stair walking. 47 // The amount the step up is applying. Used to smooth stair walking.
48 float m_lastStepUp; 48 float m_lastStepUp;
49 49
50 // There are times the velocity is set but we don't want to inforce stationary until the 50 // There are times the velocity or force is set but we don't want to inforce
51 // real velocity drops. 51 // stationary until some tick in the future and the real velocity drops.
52 bool m_waitingForLowVelocityForStationary = false; 52 int m_waitingForLowVelocityForStationary = 0;
53 53
54 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) 54 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
55 : base(physicsScene, pObj, actorName) 55 : base(physicsScene, pObj, actorName)
@@ -114,14 +114,18 @@ public class BSActorAvatarMove : BSActor
114 m_velocityMotor.Enabled = true; 114 m_velocityMotor.Enabled = true;
115 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,SetVelocityAndTarget,vel={1}, targ={2}", 115 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,SetVelocityAndTarget,vel={1}, targ={2}",
116 m_controllingPrim.LocalID, vel, targ); 116 m_controllingPrim.LocalID, vel, targ);
117 m_waitingForLowVelocityForStationary = false; 117 m_waitingForLowVelocityForStationary = 0;
118 } 118 }
119 }); 119 });
120 } 120 }
121 121
122 public void SuppressStationayCheckUntilLowVelocity() 122 public void SuppressStationayCheckUntilLowVelocity()
123 { 123 {
124 m_waitingForLowVelocityForStationary = true; 124 m_waitingForLowVelocityForStationary = 1;
125 }
126 public void SuppressStationayCheckUntilLowVelocity(int waitTicks)
127 {
128 m_waitingForLowVelocityForStationary = waitTicks;
125 } 129 }
126 130
127 // If a movement motor has not been created, create one and start the movement 131 // If a movement motor has not been created, create one and start the movement
@@ -143,7 +147,7 @@ public class BSActorAvatarMove : BSActor
143 m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty; 147 m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
144 148
145 m_walkingUpStairs = 0; 149 m_walkingUpStairs = 0;
146 m_waitingForLowVelocityForStationary = false; 150 m_waitingForLowVelocityForStationary = 0;
147 } 151 }
148 } 152 }
149 153
@@ -194,15 +198,17 @@ public class BSActorAvatarMove : BSActor
194 // if colliding with something stationary and we're not doing volume detect . 198 // if colliding with something stationary and we're not doing volume detect .
195 if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect) 199 if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect)
196 { 200 {
197 if (m_waitingForLowVelocityForStationary) 201 if (m_waitingForLowVelocityForStationary-- <= 0)
198 { 202 {
199 // if waiting for velocity to drop and it has finally dropped, we can be stationary 203 // if waiting for velocity to drop and it has finally dropped, we can be stationary
204 // m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,waitingForLowVelocity {1}",
205 // m_controllingPrim.LocalID, m_waitingForLowVelocityForStationary);
200 if (m_controllingPrim.RawVelocity.LengthSquared() < BSParam.AvatarStopZeroThresholdSquared) 206 if (m_controllingPrim.RawVelocity.LengthSquared() < BSParam.AvatarStopZeroThresholdSquared)
201 { 207 {
202 m_waitingForLowVelocityForStationary = false; 208 m_waitingForLowVelocityForStationary = 0;
203 } 209 }
204 } 210 }
205 if (!m_waitingForLowVelocityForStationary) 211 if (m_waitingForLowVelocityForStationary <= 0)
206 { 212 {
207 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID); 213 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
208 m_controllingPrim.IsStationary = true; 214 m_controllingPrim.IsStationary = true;
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
index 2ca7dbc..f971e59 100644..100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
@@ -701,7 +701,7 @@ public sealed class BSCharacter : BSPhysObject
701 } 701 }
702 if (m_moveActor != null) 702 if (m_moveActor != null)
703 { 703 {
704 m_moveActor.SuppressStationayCheckUntilLowVelocity(); 704 m_moveActor.SuppressStationayCheckUntilLowVelocity(BSParam.AvatarAddForceFrames);
705 } 705 }
706 }); 706 });
707 } 707 }
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs
index 495f752..d80b050 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSParam.cs
@@ -149,6 +149,7 @@ public static class BSParam
149 public static float AvatarHeightHighFudge { get; private set; } 149 public static float AvatarHeightHighFudge { get; private set; }
150 public static float AvatarFlyingGroundMargin { get; private set; } 150 public static float AvatarFlyingGroundMargin { get; private set; }
151 public static float AvatarFlyingGroundUpForce { get; private set; } 151 public static float AvatarFlyingGroundUpForce { get; private set; }
152 public static int AvatarAddForceFrames { get; private set; }
152 public static float AvatarTerminalVelocity { get; private set; } 153 public static float AvatarTerminalVelocity { get; private set; }
153 public static float AvatarContactProcessingThreshold { get; private set; } 154 public static float AvatarContactProcessingThreshold { get; private set; }
154 public static float AvatarAddForcePushFactor { get; private set; } 155 public static float AvatarAddForcePushFactor { get; private set; }
@@ -634,6 +635,8 @@ public static class BSParam
634 5f ), 635 5f ),
635 new ParameterDefn<float>("AvatarFlyingGroundUpForce", "Upward force applied to the avatar to keep it at flying ground margin", 636 new ParameterDefn<float>("AvatarFlyingGroundUpForce", "Upward force applied to the avatar to keep it at flying ground margin",
636 2.0f ), 637 2.0f ),
638 new ParameterDefn<int>("AvatarAddForceFrames", "Frames to allow AddForce to apply before checking for stationary",
639 10 ),
637 new ParameterDefn<float>("AvatarTerminalVelocity", "Terminal Velocity of falling avatar", 640 new ParameterDefn<float>("AvatarTerminalVelocity", "Terminal Velocity of falling avatar",
638 -54.0f ), 641 -54.0f ),
639 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 642 new ParameterDefn<float>("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
index 3120d04..a6a2dd8 100644..100755
--- 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
221 /// </summary> 221 /// </summary>
222 private static void CmdHandlerThreadLoop() 222 private static void CmdHandlerThreadLoop()
223 { 223 {
224 while (true) 224 bool running = true;
225 while (running)
225 { 226 {
226 try 227 try
227 { 228 {
@@ -230,7 +231,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
230 DoOneCmdHandlerPass(); 231 DoOneCmdHandlerPass();
231 Watchdog.UpdateThread(); 232 Watchdog.UpdateThread();
232 } 233 }
233 catch ( System.Threading.ThreadAbortException) { } 234 catch ( System.Threading.ThreadAbortException)
235 {
236 Thread.ResetAbort();
237 running = false;
238 }
234 catch (Exception e) 239 catch (Exception e)
235 { 240 {
236 m_log.Error("[ASYNC COMMAND MANAGER]: Exception in command handler pass: ", e); 241 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 943141c..ab3562f 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
1936 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 1936 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1937 return; 1937 return;
1938 1938
1939 Primitive.TextureEntry tex = part.Shape.Textures;
1940 int nsides = GetNumberOfSides(part);
1941 Color4 texcolor;
1942
1943 if (face >= 0 && face < nsides)
1944 {
1945 texcolor = tex.CreateFace((uint)face).RGBA;
1946 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1947 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1948 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1949 tex.FaceTextures[face].RGBA = texcolor;
1950 part.UpdateTextureEntry(tex);
1951 return;
1952 }
1953 else if (face == ScriptBaseClass.ALL_SIDES)
1954 {
1955 for (uint i = 0; i < nsides; i++)
1956 {
1957 if (tex.FaceTextures[i] != null)
1958 {
1959 texcolor = tex.FaceTextures[i].RGBA;
1960 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1961 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1962 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1963 tex.FaceTextures[i].RGBA = texcolor;
1964 }
1965 texcolor = tex.DefaultTexture.RGBA;
1966 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1967 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1968 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1969 tex.DefaultTexture.RGBA = texcolor;
1970 }
1971 part.UpdateTextureEntry(tex);
1972 return;
1973 }
1974
1975 if (face == ScriptBaseClass.ALL_SIDES)
1976 face = SceneObjectPart.ALL_SIDES;
1977
1978 m_host.SetFaceColorAlpha(face, color, null); 1939 m_host.SetFaceColorAlpha(face, color, null);
1979 } 1940 }
1980 1941
@@ -3577,7 +3538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3577 public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot) 3538 public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot)
3578 { 3539 {
3579 m_host.AddScriptLPS(1); 3540 m_host.AddScriptLPS(1);
3580 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) 3541 if (string.IsNullOrEmpty(inventory) || Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
3581 return; 3542 return;
3582 3543
3583 float dist = (float)llVecDist(llGetPos(), pos); 3544 float dist = (float)llVecDist(llGetPos(), pos);
@@ -10653,7 +10614,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10653 return false; 10614 return false;
10654 10615
10655 texface.MaterialID = id; 10616 texface.MaterialID = id;
10656 part.Shape.TextureEntry = tex.GetBytes(); 10617 part.Shape.TextureEntry = tex.GetBytes(9);
10657 m_materialsModule.RemoveMaterial(oldid); 10618 m_materialsModule.RemoveMaterial(oldid);
10658 return true; 10619 return true;
10659 } 10620 }
@@ -10710,7 +10671,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10710 return false; 10671 return false;
10711 10672
10712 texface.MaterialID = id; 10673 texface.MaterialID = id;
10713 part.Shape.TextureEntry = tex.GetBytes(); 10674 part.Shape.TextureEntry = tex.GetBytes(9);
10714 m_materialsModule.RemoveMaterial(oldid); 10675 m_materialsModule.RemoveMaterial(oldid);
10715 return true; 10676 return true;
10716 } 10677 }
@@ -10777,7 +10738,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10777 return false; 10738 return false;
10778 10739
10779 texface.MaterialID = id; 10740 texface.MaterialID = id;
10780 part.Shape.TextureEntry = tex.GetBytes(); 10741 part.Shape.TextureEntry = tex.GetBytes(9);
10781 m_materialsModule.RemoveMaterial(oldid); 10742 m_materialsModule.RemoveMaterial(oldid);
10782 return true; 10743 return true;
10783 } 10744 }
@@ -13945,14 +13906,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13945 13906
13946 public LSL_Key llHTTPRequest(string url, LSL_List parameters, string body) 13907 public LSL_Key llHTTPRequest(string url, LSL_List parameters, string body)
13947 { 13908 {
13948 // Partial implementation: support for parameter flags needed
13949 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
13950 // parameter flags support are implemented in ScriptsHttpRequests.cs
13951 // in StartHttpRequest
13952
13953 m_host.AddScriptLPS(1); 13909 m_host.AddScriptLPS(1);
13954 IHttpRequestModule httpScriptMod = 13910 IHttpRequestModule httpScriptMod = m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
13955 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); 13911 if(httpScriptMod == null)
13912 return "";
13913
13914 if(!httpScriptMod.CheckThrottle(m_host.LocalId, m_host.OwnerID))
13915 return UUID.Zero.ToString();
13916
13956 List<string> param = new List<string>(); 13917 List<string> param = new List<string>();
13957 bool ok; 13918 bool ok;
13958 Int32 flag; 13919 Int32 flag;
@@ -14123,8 +14084,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14123 } 14084 }
14124 14085
14125 HttpInitialRequestStatus status; 14086 HttpInitialRequestStatus status;
14126 UUID reqID 14087 UUID reqID = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
14127 = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
14128 14088
14129 if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER) 14089 if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER)
14130 Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url)); 14090 Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url));
@@ -14132,7 +14092,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14132 if (reqID != UUID.Zero) 14092 if (reqID != UUID.Zero)
14133 return reqID.ToString(); 14093 return reqID.ToString();
14134 else 14094 else
14135 return null; 14095 return "";
14136 } 14096 }
14137 14097
14138 14098
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 9d5f670..dabd399 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
3629 { 3629 {
3630 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); 3630 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
3631 3631
3632 World.ForEachRootScenePresence(delegate(ScenePresence sp) 3632 World.ForEachRootScenePresence(delegate (ScenePresence sp)
3633 { 3633 {
3634 if (sp.Firstname == FirstName && sp.Lastname == SurName) 3634 if (sp.Firstname == FirstName && sp.Lastname == SurName)
3635 { 3635 {
@@ -3643,18 +3643,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3643 }); 3643 });
3644 } 3644 }
3645 3645
3646 public LSL_Float osGetHealth(string avatar) 3646 public void osKickAvatar(LSL_Key agentKey, string alert)
3647 {
3648 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
3649
3650 UUID id;
3651 if (!UUID.TryParse(agentKey, out id) || id == UUID.Zero)
3652 return;
3653
3654 ScenePresence sp = World.GetScenePresence(id);
3655 if(sp == null)
3656 return;
3657
3658 // kick client...
3659 if (alert != null)
3660 sp.ControllingClient.Kick(alert);
3661
3662 // ...and close on our side
3663 sp.Scene.CloseAgent(id, false);
3664 }
3665
3666 public LSL_Float osGetHealth(LSL_Key agentKey)
3647 { 3667 {
3648 CheckThreatLevel(ThreatLevel.None, "osGetHealth"); 3668 CheckThreatLevel(ThreatLevel.None, "osGetHealth");
3649 3669
3650 LSL_Float health = new LSL_Float(-1); 3670 LSL_Float health = new LSL_Float(-1);
3651 ScenePresence presence = World.GetScenePresence(new UUID(avatar)); 3671
3672 UUID id;
3673 if (!UUID.TryParse(agentKey, out id) || id == UUID.Zero)
3674 return health;
3675
3676 ScenePresence presence = World.GetScenePresence(id);
3652 if (presence != null) 3677 if (presence != null)
3653 health = presence.Health; 3678 health = presence.Health;
3654 return health; 3679 return health;
3655 } 3680 }
3656 3681
3657 public void osCauseDamage(string avatar, double damage) 3682 public void osCauseDamage(LSL_Key avatar, LSL_Float damage)
3658 { 3683 {
3659 CheckThreatLevel(ThreatLevel.High, "osCauseDamage"); 3684 CheckThreatLevel(ThreatLevel.High, "osCauseDamage");
3660 3685
@@ -3683,7 +3708,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3683 } 3708 }
3684 } 3709 }
3685 3710
3686 public void osCauseHealing(string avatar, double healing) 3711 public void osCauseHealing(LSL_Key avatar, LSL_Float healing)
3687 { 3712 {
3688 CheckThreatLevel(ThreatLevel.High, "osCauseHealing"); 3713 CheckThreatLevel(ThreatLevel.High, "osCauseHealing");
3689 3714
@@ -3704,7 +3729,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3704 presence.setHealthWithUpdate(health); 3729 presence.setHealthWithUpdate(health);
3705 } 3730 }
3706 3731
3707 public void osSetHealth(string avatar, double health) 3732 public void osSetHealth(LSL_Key avatar, LSL_Float health)
3708 { 3733 {
3709 CheckThreatLevel(ThreatLevel.High, "osSetHealth"); 3734 CheckThreatLevel(ThreatLevel.High, "osSetHealth");
3710 3735
@@ -3722,7 +3747,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3722 } 3747 }
3723 } 3748 }
3724 3749
3725 public void osSetHealRate(string avatar, double healrate) 3750 public void osSetHealRate(LSL_Key avatar, LSL_Float healrate)
3726 { 3751 {
3727 CheckThreatLevel(ThreatLevel.High, "osSetHealRate"); 3752 CheckThreatLevel(ThreatLevel.High, "osSetHealRate");
3728 3753
@@ -3737,7 +3762,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3737 presence.HealRate = (float)healrate; 3762 presence.HealRate = (float)healrate;
3738 } 3763 }
3739 3764
3740 public LSL_Float osGetHealRate(string avatar) 3765 public LSL_Float osGetHealRate(LSL_Key avatar)
3741 { 3766 {
3742 CheckThreatLevel(ThreatLevel.None, "osGetHealRate"); 3767 CheckThreatLevel(ThreatLevel.None, "osGetHealRate");
3743 3768
@@ -3865,29 +3890,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3865 } 3890 }
3866 3891
3867 /// <summary> 3892 /// <summary>
3868 /// Get the description from an inventory item
3869 /// </summary>
3870 /// <param name="inventoryName"></param>
3871 /// <returns>Item description</returns>
3872 public LSL_String osGetInventoryDesc(string item)
3873 {
3874 CheckThreatLevel();
3875
3876 lock (m_host.TaskInventory)
3877 {
3878 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
3879 {
3880 if (inv.Value.Name == item)
3881 {
3882 return inv.Value.Description.ToString();
3883 }
3884 }
3885 }
3886
3887 return String.Empty;
3888 }
3889
3890 /// <summary>
3891 /// Invite user to the group this object is set to 3893 /// Invite user to the group this object is set to
3892 /// </summary> 3894 /// </summary>
3893 /// <param name="agentId"></param> 3895 /// <param name="agentId"></param>
@@ -4849,8 +4851,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4849 return Math.Atan2(mcross, dot); 4851 return Math.Atan2(mcross, dot);
4850 } 4852 }
4851 4853
4852
4853//******* link sound
4854 public void osAdjustSoundVolume(LSL_Integer linknum, LSL_Float volume) 4854 public void osAdjustSoundVolume(LSL_Integer linknum, LSL_Float volume)
4855 { 4855 {
4856 m_host.AddScriptLPS(1); 4856 m_host.AddScriptLPS(1);
@@ -5381,5 +5381,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5381 return 1; 5381 return 1;
5382 } 5382 }
5383 5383
5384 public LSL_Key osGetInventoryLastOwner(LSL_String itemNameorid)
5385 {
5386 m_host.AddScriptLPS(1);
5387
5388 TaskInventoryItem item = null;
5389 UUID itemID;
5390 if (UUID.TryParse(itemNameorid, out itemID))
5391 item = m_host.Inventory.GetInventoryItem(itemID);
5392 else
5393 item = m_host.Inventory.GetInventoryItem(itemNameorid);
5394
5395 if (item == null)
5396 return UUID.Zero.ToString();
5397
5398 UUID id = item.LastOwnerID;
5399 if(id == UUID.Zero)
5400 id= item.OwnerID;
5401 return id.ToString();
5402 }
5403
5404 public LSL_String osGetInventoryName(LSL_Key itemId)
5405 {
5406 m_host.AddScriptLPS(1);
5407
5408 TaskInventoryItem item = null;
5409 UUID itemID;
5410 if (UUID.TryParse(itemId, out itemID))
5411 item = m_host.Inventory.GetInventoryItem(itemID);
5412
5413 if (item == null)
5414 return String.Empty;
5415
5416 return item.Name;
5417 }
5418
5419 public LSL_String osGetInventoryDesc(LSL_String itemNameorid)
5420 {
5421 m_host.AddScriptLPS(1);
5422
5423 TaskInventoryItem item = null;
5424 UUID itemID;
5425 if (UUID.TryParse(itemNameorid, out itemID))
5426 item = m_host.Inventory.GetInventoryItem(itemID);
5427 else
5428 item = m_host.Inventory.GetInventoryItem(itemNameorid);
5429
5430 if (item == null)
5431 return String.Empty;
5432
5433 return item.Description;
5434 }
5435
5436 public LSL_Key osGetLastChangedEventKey()
5437 {
5438 m_host.AddScriptLPS(1);
5439 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
5440 if (detectedParams == null)
5441 return String.Empty;
5442 return detectedParams.Key.ToString();
5443 }
5384 } 5444 }
5385} \ No newline at end of file 5445} \ 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 629b14b..166f2d9 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
48 if (m_CmdManager.m_ScriptEngine.World == null) 48 if (m_CmdManager.m_ScriptEngine.World == null)
49 return; 49 return;
50 50
51 IHttpRequestModule iHttpReq = 51 IHttpRequestModule iHttpReq = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
52 m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); 52 if(iHttpReq == null)
53 53 return;
54 HttpRequestClass httpInfo = null;
55
56 if (iHttpReq != null)
57 httpInfo = (HttpRequestClass)iHttpReq.GetNextCompletedRequest();
58 54
55 HttpRequestClass httpInfo = (HttpRequestClass)iHttpReq.GetNextCompletedRequest();
59 while (httpInfo != null) 56 while (httpInfo != null)
60 { 57 {
61 //m_log.Debug("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status); 58 //m_log.Debug("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status);
@@ -67,8 +64,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
67 // implemented here yet anyway. Should be fixed if/when maxsize 64 // implemented here yet anyway. Should be fixed if/when maxsize
68 // is supported 65 // is supported
69 66
70 iHttpReq.RemoveCompletedRequest(httpInfo.ReqID);
71
72 object[] resobj = new object[] 67 object[] resobj = new object[]
73 { 68 {
74 new LSL_Types.LSLString(httpInfo.ReqID.ToString()), 69 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 12e8103..49b3f74 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
379 379
380 int osGetSimulatorMemory(); 380 int osGetSimulatorMemory();
381 int osGetSimulatorMemoryKB(); 381 int osGetSimulatorMemoryKB();
382 void osKickAvatar(string FirstName,string SurName,string alert); 382 void osKickAvatar(string FirstName, string SurName, string alert);
383 void osKickAvatar(LSL_Key agentId, string alert);
383 void osSetSpeed(string UUID, LSL_Float SpeedModifier); 384 void osSetSpeed(string UUID, LSL_Float SpeedModifier);
384 void osSetOwnerSpeed(LSL_Float SpeedModifier); 385 void osSetOwnerSpeed(LSL_Float SpeedModifier);
385 LSL_Float osGetHealth(string avatar); 386 LSL_Float osGetHealth(key agentId);
386 void osCauseHealing(string avatar, double healing); 387 void osCauseHealing(key agentId, LSL_Float healing);
387 void osSetHealth(string avatar, double health); 388 void osSetHealth(key agentId, LSL_Float health);
388 void osSetHealRate(string avatar, double health); 389 void osSetHealRate(key agentId, LSL_Float health);
389 LSL_Float osGetHealRate(string avatar); 390 LSL_Float osGetHealRate(key agentId);
390 void osCauseDamage(string avatar, double damage); 391 void osCauseDamage(key avatar, LSL_Float damage);
391 void osForceOtherSit(string avatar); 392 void osForceOtherSit(string avatar);
392 void osForceOtherSit(string avatar, string target); 393 void osForceOtherSit(string avatar, string target);
393 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); 394 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
@@ -400,8 +401,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
400 401
401 LSL_String osUnixTimeToTimestamp(LSL_Integer time); 402 LSL_String osUnixTimeToTimestamp(LSL_Integer time);
402 403
403 LSL_String osGetInventoryDesc(string item);
404
405 LSL_Integer osInviteToGroup(LSL_Key agentId); 404 LSL_Integer osInviteToGroup(LSL_Key agentId);
406 LSL_Integer osEjectFromGroup(LSL_Key agentId); 405 LSL_Integer osEjectFromGroup(LSL_Key agentId);
407 406
@@ -546,5 +545,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
546 LSL_Integer osApproxEquals(vector va, vector vb, LSL_Float margin); 545 LSL_Integer osApproxEquals(vector va, vector vb, LSL_Float margin);
547 LSL_Integer osApproxEquals(rotation ra, rotation rb); 546 LSL_Integer osApproxEquals(rotation ra, rotation rb);
548 LSL_Integer osApproxEquals(rotation ra, rotation rb, LSL_Float margin); 547 LSL_Integer osApproxEquals(rotation ra, rotation rb, LSL_Float margin);
548 LSL_Key osGetInventoryLastOwner(LSL_String itemNameOrId);
549 LSL_String osGetInventoryName(LSL_Key itemId);
550 LSL_String osGetInventoryDesc(LSL_String itemNameOrId);
551 LSL_Key osGetLastChangedEventKey();
549 } 552 }
550} 553}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 49f46b7..8b70128 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
35 public partial class ScriptBaseClass 35 public partial class ScriptBaseClass
36 { 36 {
37 // SCRIPTS CONSTANTS 37 // SCRIPTS CONSTANTS
38 public static readonly LSLInteger OS_APIVERSION = 2; 38 public static readonly LSLInteger OS_APIVERSION = 3;
39 39
40 public static readonly LSLInteger TRUE = 1; 40 public static readonly LSLInteger TRUE = 1;
41 public static readonly LSLInteger FALSE = 0; 41 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 94df1ea..fb491e4 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
965 return m_OSSL_Functions.osGetSimulatorMemoryKB(); 965 return m_OSSL_Functions.osGetSimulatorMemoryKB();
966 } 966 }
967 967
968 public void osKickAvatar(string FirstName,string SurName,string alert) 968 public void osKickAvatar(string FirstName, string SurName, string alert)
969 { 969 {
970 m_OSSL_Functions.osKickAvatar(FirstName, SurName, alert); 970 m_OSSL_Functions.osKickAvatar(FirstName, SurName, alert);
971 } 971 }
972 972
973 public void osKickAvatar(LSL_Key agentId, string alert)
974 {
975 m_OSSL_Functions.osKickAvatar(agentId, alert);
976 }
977
973 public void osSetSpeed(string UUID, LSL_Float SpeedModifier) 978 public void osSetSpeed(string UUID, LSL_Float SpeedModifier)
974 { 979 {
975 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); 980 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
@@ -980,32 +985,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
980 m_OSSL_Functions.osSetOwnerSpeed(SpeedModifier); 985 m_OSSL_Functions.osSetOwnerSpeed(SpeedModifier);
981 } 986 }
982 987
983 public LSL_Float osGetHealth(string avatar) 988 public LSL_Float osGetHealth(key avatar)
984 { 989 {
985 return m_OSSL_Functions.osGetHealth(avatar); 990 return m_OSSL_Functions.osGetHealth(avatar);
986 } 991 }
987 992
988 public void osCauseDamage(string avatar, double damage) 993 public void osCauseDamage(key avatar, LSL_Float damage)
989 { 994 {
990 m_OSSL_Functions.osCauseDamage(avatar, damage); 995 m_OSSL_Functions.osCauseDamage(avatar, damage);
991 } 996 }
992 997
993 public void osCauseHealing(string avatar, double healing) 998 public void osCauseHealing(key avatar, LSL_Float healing)
994 { 999 {
995 m_OSSL_Functions.osCauseHealing(avatar, healing); 1000 m_OSSL_Functions.osCauseHealing(avatar, healing);
996 } 1001 }
997 1002
998 public void osSetHealth(string avatar, double health) 1003 public void osSetHealth(key avatar, LSL_Float health)
999 { 1004 {
1000 m_OSSL_Functions.osSetHealth(avatar, health); 1005 m_OSSL_Functions.osSetHealth(avatar, health);
1001 } 1006 }
1002 1007
1003 public void osSetHealRate(string avatar, double health) 1008 public void osSetHealRate(key avatar, LSL_Float health)
1004 { 1009 {
1005 m_OSSL_Functions.osSetHealRate(avatar, health); 1010 m_OSSL_Functions.osSetHealRate(avatar, health);
1006 } 1011 }
1007 1012
1008 public LSL_Float osGetHealRate(string avatar) 1013 public LSL_Float osGetHealRate(key avatar)
1009 { 1014 {
1010 return m_OSSL_Functions.osGetHealRate(avatar); 1015 return m_OSSL_Functions.osGetHealRate(avatar);
1011 } 1016 }
@@ -1055,11 +1060,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1055 return m_OSSL_Functions.osUnixTimeToTimestamp(time); 1060 return m_OSSL_Functions.osUnixTimeToTimestamp(time);
1056 } 1061 }
1057 1062
1058 public LSL_String osGetInventoryDesc(string item)
1059 {
1060 return m_OSSL_Functions.osGetInventoryDesc(item);
1061 }
1062
1063 public LSL_Integer osInviteToGroup(LSL_Key agentId) 1063 public LSL_Integer osInviteToGroup(LSL_Key agentId)
1064 { 1064 {
1065 return m_OSSL_Functions.osInviteToGroup(agentId); 1065 return m_OSSL_Functions.osInviteToGroup(agentId);
@@ -1361,5 +1361,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1361 { 1361 {
1362 return m_OSSL_Functions.osApproxEquals(ra, rb, margin); 1362 return m_OSSL_Functions.osApproxEquals(ra, rb, margin);
1363 } 1363 }
1364
1365 public LSL_Key osGetInventoryLastOwner(LSL_String itemNameOrId)
1366 {
1367 return m_OSSL_Functions.osGetInventoryLastOwner(itemNameOrId);
1368 }
1369
1370 public LSL_String osGetInventoryName(LSL_Key itemId)
1371 {
1372 return m_OSSL_Functions.osGetInventoryName(itemId);
1373 }
1374
1375 public LSL_String osGetInventoryDesc(LSL_String itemNameOrId)
1376 {
1377 return m_OSSL_Functions.osGetInventoryDesc(itemNameOrId);
1378 }
1379
1380 public LSL_Key osGetLastChangedEventKey()
1381 {
1382 return m_OSSL_Functions.osGetLastChangedEventKey();
1383 }
1364 } 1384 }
1365} 1385}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 019a0d9..351fca9 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
699 // If min event delay is set then ignore any events untill the time has expired 699 // If min event delay is set then ignore any events untill the time has expired
700 // This currently only allows 1 event of any type in the given time period. 700 // This currently only allows 1 event of any type in the given time period.
701 // This may need extending to allow for a time for each individual event type. 701 // This may need extending to allow for a time for each individual event type.
702 if (m_eventDelayTicks != 0) 702 if (m_eventDelayTicks != 0 &&
703 data.EventName != "state" && data.EventName != "state_entry" && data.EventName != "state_exit"
704 && data.EventName != "run_time_permissions" && data.EventName != "http_request" && data.EventName != "link_message")
703 { 705 {
704 if (DateTime.Now.Ticks < m_nextEventTimeTicks) 706 if (DateTime.Now.Ticks < m_nextEventTimeTicks)
705 return; 707 return;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index b7fc161..50a95a9 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -215,12 +215,25 @@ namespace OpenSim.Region.ScriptEngine.XEngine
215 det)); 215 det));
216 } 216 }
217 217
218 public void changed(uint localID, uint change) 218 public void changed(uint localID, uint change, object parameter)
219 { 219 {
220 // Add to queue for all scripts in localID, Object pass change. 220 // Add to queue for all scripts in localID, Object pass change.
221 myScriptEngine.PostObjectEvent(localID, new EventParams( 221 if(parameter == null)
222 "changed",new object[] { new LSL_Types.LSLInteger(change) }, 222 {
223 myScriptEngine.PostObjectEvent(localID, new EventParams(
224 "changed", new object[] { new LSL_Types.LSLInteger(change) },
223 new DetectParams[0])); 225 new DetectParams[0]));
226 return;
227 }
228 if (parameter is UUID)
229 {
230 DetectParams det = new DetectParams();
231 det.Key = (UUID)parameter;
232 myScriptEngine.PostObjectEvent(localID, new EventParams(
233 "changed", new object[] { new LSL_Types.LSLInteger(change) },
234 new DetectParams[] { det }));
235 return;
236 }
224 } 237 }
225 238
226 // state_entry: not processed here 239 // state_entry: not processed here
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs
index c00e8d4..3539fa1 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptEventCode.cs
@@ -88,10 +88,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
88 88
89 path_update = 40, 89 path_update = 40,
90 90
91 // XMRE specific
92 region_cross = 63,
93
94 // marks highest numbered event, ie, number of columns in seht. 91 // marks highest numbered event, ie, number of columns in seht.
95 Size = 64 92 Size = 41
96 } 93 }
97} 94}
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs
index 017b294..6acc293 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs
@@ -930,12 +930,15 @@ namespace OpenSim.Region.ScriptEngine.Yengine
930 930
931 public void SetMinEventDelay(UUID itemID, double delay) 931 public void SetMinEventDelay(UUID itemID, double delay)
932 { 932 {
933 XMRInstance instance = GetInstance(itemID);
934 if (instance != null)
935 instance.MinEventDelay = delay;
933 } 936 }
934 937
935 public int GetStartParameter(UUID itemID) 938 public int GetStartParameter(UUID itemID)
936 { 939 {
937 XMRInstance instance = GetInstance(itemID); 940 XMRInstance instance = GetInstance(itemID);
938 if(instance == null) 941 if (instance == null)
939 return 0; 942 return 0;
940 return instance.StartParam; 943 return instance.StartParam;
941 } 944 }
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs
index 5a8b2a3..65a8aed 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMREvents.cs
@@ -182,13 +182,26 @@ namespace OpenSim.Region.ScriptEngine.Yengine
182 new DetectParams[] { det })); 182 new DetectParams[] { det }));
183 } 183 }
184 184
185 public void changed(uint localID, uint change) 185 public void changed(uint localID, uint change, object parameter)
186 { 186 {
187 int ch = (int)change; 187 int ch = (int)change;
188 // Add to queue for all scripts in localID, Object pass change. 188 // Add to queue for all scripts in localID, Object pass change.
189 this.PostObjectEvent(localID, new EventParams( 189 if(parameter == null)
190 {
191 PostObjectEvent(localID, new EventParams(
190 "changed", new object[] { ch }, 192 "changed", new object[] { ch },
191 zeroDetectParams)); 193 zeroDetectParams));
194 return;
195 }
196 if ( parameter is UUID)
197 {
198 DetectParams det = new DetectParams();
199 det.Key = (UUID)parameter;
200 PostObjectEvent(localID, new EventParams(
201 "changed", new object[] { ch },
202 new DetectParams[] { det }));
203 return;
204 }
192 } 205 }
193 206
194 // state_entry: not processed here 207 // state_entry: not processed here
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs
index 6fe11d8..7fc97e9 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs
@@ -422,9 +422,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
422 object[] saveEHArgs = this.ehArgs; 422 object[] saveEHArgs = this.ehArgs;
423 ScriptEventCode saveEventCode = this.eventCode; 423 ScriptEventCode saveEventCode = this.eventCode;
424 424
425 this.m_DetectParams = evt.DetectParams; 425 m_DetectParams = evt.DetectParams;
426 this.ehArgs = evt.Params; 426 ehArgs = evt.Params;
427 this.eventCode = evc; 427 eventCode = evc;
428 428
429 try 429 try
430 { 430 {
@@ -432,9 +432,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
432 } 432 }
433 finally 433 finally
434 { 434 {
435 this.m_DetectParams = saveDetParams; 435 m_DetectParams = saveDetParams;
436 this.ehArgs = saveEHArgs; 436 ehArgs = saveEHArgs;
437 this.eventCode = saveEventCode; 437 eventCode = saveEventCode;
438 } 438 }
439 439
440 // Keep waiting until we find a returnable event or timeout. 440 // 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 9bb894d..5798638 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs
@@ -115,6 +115,15 @@ namespace OpenSim.Region.ScriptEngine.Yengine
115 m_RunOnePhase = "GetExecutionState D"; 115 m_RunOnePhase = "GetExecutionState D";
116 CheckRunLockInvariants(true); 116 CheckRunLockInvariants(true);
117 117
118 if (m_minEventDelay != 0.0)
119 {
120 XmlElement minEventDelayN = doc.CreateElement("", "mEvtDly", "");
121 minEventDelayN.AppendChild(doc.CreateTextNode(m_minEventDelay.ToString()));
122 scriptStateN.AppendChild(minEventDelayN);
123 m_RunOnePhase = "GetExecutionState D";
124 CheckRunLockInvariants(true);
125 }
126
118 // More misc data. 127 // More misc data.
119 XmlNode permissionsN = doc.CreateElement("", "Permissions", ""); 128 XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
120 scriptStateN.AppendChild(permissionsN); 129 scriptStateN.AppendChild(permissionsN);
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs
index b140453..7e13ae4 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs
@@ -527,6 +527,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
527 XmlElement doGblInitN = (XmlElement)scriptStateN.SelectSingleNode("DoGblInit"); 527 XmlElement doGblInitN = (XmlElement)scriptStateN.SelectSingleNode("DoGblInit");
528 doGblInit = bool.Parse(doGblInitN.InnerText); 528 doGblInit = bool.Parse(doGblInitN.InnerText);
529 529
530 double minEventDelay = 0.0;
531 XmlElement minEventDelayN = (XmlElement)scriptStateN.SelectSingleNode("mEvtDly");
532 if(minEventDelayN != null)
533 minEventDelay = Double.Parse(minEventDelayN.InnerText);
534
530 // get values used by stuff like llDetectedGrab, etc. 535 // get values used by stuff like llDetectedGrab, etc.
531 DetectParams[] detParams = RestoreDetectParams(scriptStateN.SelectSingleNode("DetectArray")); 536 DetectParams[] detParams = RestoreDetectParams(scriptStateN.SelectSingleNode("DetectArray"));
532 537
@@ -576,6 +581,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
576 AsyncCommandManager.CreateFromData(m_Engine, 581 AsyncCommandManager.CreateFromData(m_Engine,
577 m_LocalID, m_ItemID, m_Part.UUID, 582 m_LocalID, m_ItemID, m_Part.UUID,
578 pluginData); 583 pluginData);
584
585 MinEventDelay = minEventDelay;
579 } 586 }
580 587
581 private void processXstate(XmlDocument doc) 588 private void processXstate(XmlDocument doc)
@@ -919,6 +926,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
919 926
920 AsyncCommandManager.CreateFromData(m_Engine, 927 AsyncCommandManager.CreateFromData(m_Engine,
921 m_LocalID, m_ItemID, m_Part.UUID, pluginData); 928 m_LocalID, m_ItemID, m_Part.UUID, pluginData);
929
930 MinEventDelay = minEventDelay;
922 } 931 }
923 932
924 private static void getvarNames(Dictionary<int, string> s, Dictionary<string, int> d) 933 private static void getvarNames(Dictionary<int, string> s, Dictionary<string, int> d)
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs
index 3c0040c..def06b2 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMain.cs
@@ -215,5 +215,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
215 // It's born ready, but will be reset when the detach is posted. 215 // It's born ready, but will be reset when the detach is posted.
216 // It will then be set again on suspend/completion 216 // It will then be set again on suspend/completion
217 private ManualResetEvent m_DetachReady = new ManualResetEvent(true); 217 private ManualResetEvent m_DetachReady = new ManualResetEvent(true);
218
219 // llmineventdelay support
220 double m_minEventDelay = 0.0;
221 double m_nextEventTime = 0.0;
218 } 222 }
219} 223}
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs
index 0af3d37..12feb7b 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs
@@ -298,6 +298,24 @@ namespace OpenSim.Region.ScriptEngine.Yengine
298 } 298 }
299 } 299 }
300 300
301 public double MinEventDelay
302 {
303 get
304 {
305 return m_minEventDelay;
306 }
307 set
308 {
309 if (value > 0.001)
310 m_minEventDelay = value;
311 else
312 m_minEventDelay = 0.0;
313
314 m_nextEventTime = 0.0; // reset it
315 }
316 }
317
318
301 public SceneObjectPart SceneObject 319 public SceneObjectPart SceneObject
302 { 320 {
303 get 321 get
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs
index 6c969dc..1b735e3 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs
@@ -63,8 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
63 */ 63 */
64 public void PostEvent(EventParams evt) 64 public void PostEvent(EventParams evt)
65 { 65 {
66 ScriptEventCode evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), 66 ScriptEventCode evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt.EventName);
67 evt.EventName);
68 67
69 // Put event on end of event queue. 68 // Put event on end of event queue.
70 bool startIt = false; 69 bool startIt = false;
@@ -86,6 +85,47 @@ namespace OpenSim.Region.ScriptEngine.Yengine
86 if(!m_Running && !construct) 85 if(!m_Running && !construct)
87 return; 86 return;
88 87
88 if(m_minEventDelay != 0)
89 {
90 switch (evc)
91 {
92 // ignore some events by time set by llMinEventDelay
93 case ScriptEventCode.collision:
94 case ScriptEventCode.land_collision:
95 case ScriptEventCode.listen:
96 case ScriptEventCode.not_at_target:
97 case ScriptEventCode.not_at_rot_target:
98 case ScriptEventCode.no_sensor:
99 case ScriptEventCode.sensor:
100 case ScriptEventCode.timer:
101 case ScriptEventCode.touch:
102 {
103 double now = Util.GetTimeStamp();
104 if (now < m_nextEventTime)
105 return;
106 m_nextEventTime = now + m_minEventDelay;
107 break;
108 }
109 case ScriptEventCode.changed:
110 {
111 const int canignore = ~(CHANGED_SCALE | CHANGED_POSITION);
112 int change = (int)evt.Params[0];
113 if(change == 0) // what?
114 return;
115 if((change & canignore) == 0)
116 {
117 double now = Util.GetTimeStamp();
118 if (now < m_nextEventTime)
119 return;
120 m_nextEventTime = now + m_minEventDelay;
121 }
122 break;
123 }
124 default:
125 break;
126 }
127 }
128
89 // Only so many of each event type allowed to queue. 129 // Only so many of each event type allowed to queue.
90 if((uint)evc < (uint)m_EventCounts.Length) 130 if((uint)evc < (uint)m_EventCounts.Length)
91 { 131 {
@@ -124,10 +164,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
124 for(lln2 = m_EventQueue.First; lln2 != null; lln2 = lln2.Next) 164 for(lln2 = m_EventQueue.First; lln2 != null; lln2 = lln2.Next)
125 { 165 {
126 EventParams evt2 = lln2.Value; 166 EventParams evt2 = lln2.Value;
127 ScriptEventCode evc2 = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), 167 ScriptEventCode evc2 = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt2.EventName);
128 evt2.EventName); 168 if((evc2 != ScriptEventCode.state_entry) && (evc2 != ScriptEventCode.attach))
129 if((evc2 != ScriptEventCode.state_entry) &&
130 (evc2 != ScriptEventCode.attach))
131 break; 169 break;
132 } 170 }
133 if(lln2 == null) 171 if(lln2 == null)
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 0438673..22748cc 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -757,6 +757,14 @@ namespace OpenSim.Services.LLLoginService
757 } 757 }
758 } 758 }
759 } 759 }
760
761 //find a exact match
762 foreach(GridRegion r in regions)
763 {
764 if(string.Equals(regionName, r.RegionName, StringComparison.InvariantCultureIgnoreCase))
765 return r;
766 }
767 // else, whatever
760 return regions[0]; 768 return regions[0];
761 } 769 }
762 else 770 else